PDHCG


NamePDHCG JSON
Version 0.0.1 PyPI version JSON
download
home_pageNone
SummaryA python wrapper for PDHCG.jl
upload_time2025-02-08 09:36:16
maintainerNone
docs_urlNone
authorhongpeili
requires_pythonNone
licenseMIT
keywords optimizer
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
# PDHCG-Python
The `PDHCG-Python` project provides a Python interface for PDHCG algorithm suggested in [Restarted Primal-Dual Hybrid Conjugate Gradient Method for Large-Scale Quadratic Programming](https://arxiv.org/abs/2405.16160).

Core functions is implemented by Julia, see [PDHCG.jl](https://github.com/Huangyc98/PDHCG.jl).

For datasets mentioned in the paper, please refer to [Datasets](https://github.com/Lhongpei/QP_datasets)
## Installation

Install through PyPI

```bash
pip install pdhcg
```
If you cannot install through PyPI, please clone this repo to use PDHCG.

## Usage

### 1. Import and Initialize

```python
from pdhcg import PDHCG  
solver = PDHCG(name="My QP Solver")
```

### 2. Setting Parameters

Set solver parameters either by individual `setParam` or batch `setParams` methods.

```python
solver.setParam("time_limit", 600)
solver.setParams(gpu_flag=True, verbose_level=2)
```


### 3. Defining the Problem

You can define a problem in three ways:

- **Read from File**:

  ```python
  solver.read("path/to/problem.qps", fixformat=False)
  ```

- **Generate Random Problem**:

  ```python
  solver.setGeneratedProblem(problem_type="QP", n=100, density=0.05, seed=42)
  ```

- **Construct from Scratch**:

  ```python
  from scipy.sparse import random

  # Define the problem components as numpy arrays or sparse matrices
  objective_matrix = random(100, 100, density=0.05).toarray()
  objective_vector = np.random.randn(100)
  constraint_matrix = random(50, 100, density=0.1).toarray()
  constraint_lower_bound = np.random.randn(50)
  
  solver.setConstructedProblem(
      objective_matrix=objective_matrix,
      objective_vector=objective_vector,
      objective_constant=0.0,
      constraint_matrix=constraint_matrix,
      constraint_lower_bound=constraint_lower_bound,
      num_equalities=10,
      variable_lower_bound=np.zeros(100),
      variable_upper_bound=np.ones(100) * 10,
      isfinite_variable_lower_bound=np.full(100, True),
      isfinite_variable_upper_bound=np.full(100, True)
  )
  ```

  Notice that all matrix will be strictly converted to sparse csc matrix.

### 4. Solving the Problem

```python
solver.solve()
```

### 5. Accessing Results

After solving, retrieve various results as properties:

- **`solver.primal_solution`**: Returns the primal solution after solving.
- **`solver.dual_solution`**: Returns the dual solution after solving.
- **`solver.objective_value`**: Returns the objective function's value.
- **`solver.iteration_count`**: Returns a dictionary with outer and inner iteration counts.
- **`solver.solve_time_sec`**: Solving time in seconds.
- **`solver.kkt_error`**: The KKT error for per iterations.
- **`solver.status`**: Termination status string.

## Interpreting the output

A table of iteration stats will be printed with the following headings.

### runtime

- `#iter`: the current iteration number.
- `#kkt`: the cumulative number of times the KKT matrix is multiplied.
- `seconds`: the cumulative solve time in seconds.

### residuals

- `pr norm`: the Euclidean norm of primal residuals (i.e., the constraint violation).
- `du norm`: the Euclidean norm of the dual residuals.
- `gap`: the gap between the primal and dual objective.

### solution information

- `pr obj`: the primal objective value.
- `pr norm`: the Euclidean norm of the primal variable vector.
- `du norm`: the Euclidean norm of the dual variable vector.

### relative residuals

- `rel pr`: the Euclidean norm of the primal residuals, relative to the right-hand side.
- `rel dul`: the Euclidean norm of the dual residuals, relative to the primal linear objective.
- `rel gap`: the relative optimality gap.
  
### At the end of the run, the following summary information will be printed

- Total Iterations: The total number of Primal-Dual iterations.

- CG  iteration: The total number of Conjugate Gradient iterations.

- Solving Status: Indicating if it found an optimal solution.

## Parameters

For more details of `Rescale` and `Restart` Parameters, please refer to [Restarted Primal-Dual Hybrid Conjugate Gradient Method for Large-Scale Quadratic Programming](https://arxiv.org/abs/2405.16160).

| Category   | Parameter                       | Default Value | Description                                                                                  |
|------------|---------------------------------|---------------|----------------------------------------------------------------------------------------------|
| **Basic**  | `gpu_flag`                      | `False`       | Whether to use the GPU for computations.                                                    |
|            | `warm_up_flag`                  | `False`       | If `True`, excludes compilation time from runtime measurements.                             |
|            | `verbose_level`                 | `2`           | Verbosity level (0-9). Higher values produce more detailed output.                          |
|            | `time_limit`                    | `3600.0`      | Maximum time limit for solving in seconds.                                                  |
|            | `relat_error_tolerance`         | `1e-6`        | Relative error tolerance for solution accuracy.                                             |
|            | `iteration_limit`               | `2**31 - 1`   | Maximum number of iterations allowed.                                                       |
| **Rescale**| `ruiz_rescaling_iters`          | `10`          | Number of iterations for Ruiz rescaling.                                                    |
|            | `l2_norm_rescaling_flag`        | `False`       | Enables L2 norm rescaling if `True`.                                                        |
|            | `pock_chambolle_alpha`          | `1.0`         | Alpha parameter for the Pock-Chambolle algorithm.                                           |
| **Restart**| `artificial_restart_threshold`  | `0.2`         | Threshold for artificial restart criteria.                                                  |
|            | `sufficient_reduction`          | `0.2`         | Minimum reduction required to consider a restart as sufficient.                             |
|            | `necessary_reduction`           | `0.8`         | Reduction required for restart necessity.                                                  |
|            | `primal_weight_update_smoothing`| `0.2`         | Smoothing parameter for primal-dual weight updates.                                         |
| **Log**    | `save_flag`                     | `False`       | If `True`, saves the solver's results to a file.                                           |
|            | `saved_name`                    | `None`        | Filename for saving the result (if `save_flag` is `True`).                                  |
|            | `output_dir`                    | `None`        | Directory path for saving results.                                                          |

## Example

Below is a complete example:

```python
import numpy as np
from pdhcg import PDHCG

solver = PDHCG(name="Example QP Solver")

# Set parameters
solver.setParams(gpu_flag=False, verbose_level=1)

# Define a custom problem
objective_matrix = np.eye(10)
objective_vector = np.ones(10)
constraint_matrix = np.random.randn(5, 10)
constraint_lower_bound = np.zeros(5)

solver.setConstructedProblem(
    objective_matrix=objective_matrix,
    objective_vector=objective_vector,
    objective_constant=0.0,
    constraint_matrix=constraint_matrix,
    constraint_lower_bound=constraint_lower_bound,
    num_equalities=2,
    variable_lower_bound=np.zeros(10),
    variable_upper_bound=np.ones(10) * 5,
    isfinite_variable_lower_bound=np.full(10, True),
    isfinite_variable_upper_bound=np.full(10, True)
)

# Solve the problem
solver.solve()

# Output results
print("Objective Value:", solver.objective_value)
print("Primal Solution:", solver.primal_solution)
print("Dual Solution:", solver.dual_solution)
```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "PDHCG",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "Optimizer",
    "author": "hongpeili",
    "author_email": "ishongpeili@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/17/88/439531847d035a185fbce1494f1e4abbab4995ac5e035c1493f8ddfc9820/pdhcg-0.0.1.tar.gz",
    "platform": null,
    "description": "\n# PDHCG-Python\nThe `PDHCG-Python` project provides a Python interface for PDHCG algorithm suggested in [Restarted Primal-Dual Hybrid Conjugate Gradient Method for Large-Scale Quadratic Programming](https://arxiv.org/abs/2405.16160).\n\nCore functions is implemented by Julia, see [PDHCG.jl](https://github.com/Huangyc98/PDHCG.jl).\n\nFor datasets mentioned in the paper, please refer to [Datasets](https://github.com/Lhongpei/QP_datasets)\n## Installation\n\nInstall through PyPI\n\n```bash\npip install pdhcg\n```\nIf you cannot install through PyPI, please clone this repo to use PDHCG.\n\n## Usage\n\n### 1. Import and Initialize\n\n```python\nfrom pdhcg import PDHCG  \nsolver = PDHCG(name=\"My QP Solver\")\n```\n\n### 2. Setting Parameters\n\nSet solver parameters either by individual `setParam` or batch `setParams` methods.\n\n```python\nsolver.setParam(\"time_limit\", 600)\nsolver.setParams(gpu_flag=True, verbose_level=2)\n```\n\n\n### 3. Defining the Problem\n\nYou can define a problem in three ways:\n\n- **Read from File**:\n\n  ```python\n  solver.read(\"path/to/problem.qps\", fixformat=False)\n  ```\n\n- **Generate Random Problem**:\n\n  ```python\n  solver.setGeneratedProblem(problem_type=\"QP\", n=100, density=0.05, seed=42)\n  ```\n\n- **Construct from Scratch**:\n\n  ```python\n  from scipy.sparse import random\n\n  # Define the problem components as numpy arrays or sparse matrices\n  objective_matrix = random(100, 100, density=0.05).toarray()\n  objective_vector = np.random.randn(100)\n  constraint_matrix = random(50, 100, density=0.1).toarray()\n  constraint_lower_bound = np.random.randn(50)\n  \n  solver.setConstructedProblem(\n      objective_matrix=objective_matrix,\n      objective_vector=objective_vector,\n      objective_constant=0.0,\n      constraint_matrix=constraint_matrix,\n      constraint_lower_bound=constraint_lower_bound,\n      num_equalities=10,\n      variable_lower_bound=np.zeros(100),\n      variable_upper_bound=np.ones(100) * 10,\n      isfinite_variable_lower_bound=np.full(100, True),\n      isfinite_variable_upper_bound=np.full(100, True)\n  )\n  ```\n\n  Notice that all matrix will be strictly converted to sparse csc matrix.\n\n### 4. Solving the Problem\n\n```python\nsolver.solve()\n```\n\n### 5. Accessing Results\n\nAfter solving, retrieve various results as properties:\n\n- **`solver.primal_solution`**: Returns the primal solution after solving.\n- **`solver.dual_solution`**: Returns the dual solution after solving.\n- **`solver.objective_value`**: Returns the objective function's value.\n- **`solver.iteration_count`**: Returns a dictionary with outer and inner iteration counts.\n- **`solver.solve_time_sec`**: Solving time in seconds.\n- **`solver.kkt_error`**: The KKT error for per iterations.\n- **`solver.status`**: Termination status string.\n\n## Interpreting the output\n\nA table of iteration stats will be printed with the following headings.\n\n### runtime\n\n- `#iter`: the current iteration number.\n- `#kkt`: the cumulative number of times the KKT matrix is multiplied.\n- `seconds`: the cumulative solve time in seconds.\n\n### residuals\n\n- `pr norm`: the Euclidean norm of primal residuals (i.e., the constraint violation).\n- `du norm`: the Euclidean norm of the dual residuals.\n- `gap`: the gap between the primal and dual objective.\n\n### solution information\n\n- `pr obj`: the primal objective value.\n- `pr norm`: the Euclidean norm of the primal variable vector.\n- `du norm`: the Euclidean norm of the dual variable vector.\n\n### relative residuals\n\n- `rel pr`: the Euclidean norm of the primal residuals, relative to the right-hand side.\n- `rel dul`: the Euclidean norm of the dual residuals, relative to the primal linear objective.\n- `rel gap`: the relative optimality gap.\n  \n### At the end of the run, the following summary information will be printed\n\n- Total Iterations: The total number of Primal-Dual iterations.\n\n- CG  iteration: The total number of Conjugate Gradient iterations.\n\n- Solving Status: Indicating if it found an optimal solution.\n\n## Parameters\n\nFor more details of `Rescale` and `Restart` Parameters, please refer to [Restarted Primal-Dual Hybrid Conjugate Gradient Method for Large-Scale Quadratic Programming](https://arxiv.org/abs/2405.16160).\n\n| Category   | Parameter                       | Default Value | Description                                                                                  |\n|------------|---------------------------------|---------------|----------------------------------------------------------------------------------------------|\n| **Basic**  | `gpu_flag`                      | `False`       | Whether to use the GPU for computations.                                                    |\n|            | `warm_up_flag`                  | `False`       | If `True`, excludes compilation time from runtime measurements.                             |\n|            | `verbose_level`                 | `2`           | Verbosity level (0-9). Higher values produce more detailed output.                          |\n|            | `time_limit`                    | `3600.0`      | Maximum time limit for solving in seconds.                                                  |\n|            | `relat_error_tolerance`         | `1e-6`        | Relative error tolerance for solution accuracy.                                             |\n|            | `iteration_limit`               | `2**31 - 1`   | Maximum number of iterations allowed.                                                       |\n| **Rescale**| `ruiz_rescaling_iters`          | `10`          | Number of iterations for Ruiz rescaling.                                                    |\n|            | `l2_norm_rescaling_flag`        | `False`       | Enables L2 norm rescaling if `True`.                                                        |\n|            | `pock_chambolle_alpha`          | `1.0`         | Alpha parameter for the Pock-Chambolle algorithm.                                           |\n| **Restart**| `artificial_restart_threshold`  | `0.2`         | Threshold for artificial restart criteria.                                                  |\n|            | `sufficient_reduction`          | `0.2`         | Minimum reduction required to consider a restart as sufficient.                             |\n|            | `necessary_reduction`           | `0.8`         | Reduction required for restart necessity.                                                  |\n|            | `primal_weight_update_smoothing`| `0.2`         | Smoothing parameter for primal-dual weight updates.                                         |\n| **Log**    | `save_flag`                     | `False`       | If `True`, saves the solver's results to a file.                                           |\n|            | `saved_name`                    | `None`        | Filename for saving the result (if `save_flag` is `True`).                                  |\n|            | `output_dir`                    | `None`        | Directory path for saving results.                                                          |\n\n## Example\n\nBelow is a complete example:\n\n```python\nimport numpy as np\nfrom pdhcg import PDHCG\n\nsolver = PDHCG(name=\"Example QP Solver\")\n\n# Set parameters\nsolver.setParams(gpu_flag=False, verbose_level=1)\n\n# Define a custom problem\nobjective_matrix = np.eye(10)\nobjective_vector = np.ones(10)\nconstraint_matrix = np.random.randn(5, 10)\nconstraint_lower_bound = np.zeros(5)\n\nsolver.setConstructedProblem(\n    objective_matrix=objective_matrix,\n    objective_vector=objective_vector,\n    objective_constant=0.0,\n    constraint_matrix=constraint_matrix,\n    constraint_lower_bound=constraint_lower_bound,\n    num_equalities=2,\n    variable_lower_bound=np.zeros(10),\n    variable_upper_bound=np.ones(10) * 5,\n    isfinite_variable_lower_bound=np.full(10, True),\n    isfinite_variable_upper_bound=np.full(10, True)\n)\n\n# Solve the problem\nsolver.solve()\n\n# Output results\nprint(\"Objective Value:\", solver.objective_value)\nprint(\"Primal Solution:\", solver.primal_solution)\nprint(\"Dual Solution:\", solver.dual_solution)\n```\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A python wrapper for PDHCG.jl",
    "version": "0.0.1",
    "project_urls": null,
    "split_keywords": [
        "optimizer"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "079fde144bc380d85b1f3835df9cfd18c5f132a27e567a8a0e276c03f0a495af",
                "md5": "21cb10fad771d6672199a3e4e1c3cebc",
                "sha256": "61c036562a6ec28e53378015b651808b0f540057f8b0549ce9aadf81bd37f00e"
            },
            "downloads": -1,
            "filename": "PDHCG-0.0.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "21cb10fad771d6672199a3e4e1c3cebc",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 10779,
            "upload_time": "2025-02-08T09:36:14",
            "upload_time_iso_8601": "2025-02-08T09:36:14.555759Z",
            "url": "https://files.pythonhosted.org/packages/07/9f/de144bc380d85b1f3835df9cfd18c5f132a27e567a8a0e276c03f0a495af/PDHCG-0.0.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "1788439531847d035a185fbce1494f1e4abbab4995ac5e035c1493f8ddfc9820",
                "md5": "1647319a72c6671db5e16ed49adb4a5e",
                "sha256": "e5cdee58ff22bf3328f60e644d329c66cb85103e7bd688217b6adfbfa12f9af4"
            },
            "downloads": -1,
            "filename": "pdhcg-0.0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "1647319a72c6671db5e16ed49adb4a5e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 9883,
            "upload_time": "2025-02-08T09:36:16",
            "upload_time_iso_8601": "2025-02-08T09:36:16.866793Z",
            "url": "https://files.pythonhosted.org/packages/17/88/439531847d035a185fbce1494f1e4abbab4995ac5e035c1493f8ddfc9820/pdhcg-0.0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-02-08 09:36:16",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "pdhcg"
}
        
Elapsed time: 1.96806s