【漫漫科研路\CC++】CPLEX解SOCP问题

2024-03-24 14:58
文章标签 c++ 问题 科研 cplex 漫漫 socp

本文主要是介绍【漫漫科研路\CC++】CPLEX解SOCP问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

IBM CPLEX可以解SOCP问题,但是需要先将这个SOCP问题化为指定的格式。本文首先介绍SOCP问题,然后举例介绍如何将SOCP问题转化为CPLEX认可的输入格式并求解。

SOCP的介绍

关于SOCP问题的介绍,可以参考Boyd等人写的Convex Optimization 或者是维基百科的SOCP词条 。这里摘录Convex Optimization一书中关于SOCP的定义:

在这里插入图片描述

CPLEX求解SOCP问题

使用CPLEX求解SOCP问题,一般需要将问题转化为CPLEX可以识别的格式。CPLEX的例子ilosocpex1(位于安装目录的examples文件夹内,例如:C:\Program Files\IBM\ILOG\CPLEX_Enterprise_Server129\CPLEX_Studio\cplex\examples)给予了格式说明:
在这里插入图片描述
下面我们首先给一个直接可以使用CPLEX求解的例子,然后在此基础上考虑一个更一般的例子(需要变量替换来符合格式)。

一个简单的例子

在这里插入图片描述
如上图所示,q1, q2可以直接转化为前面提到的CPLEX认可格式。下面给出源代码如下(注意项目需要预先配置好,配置请见上一篇博文):

#include <cmath>
#include <string>
#include <iostream>
#include <ilcplex/ilocplex.h>ILOSTLBEGIN // import namespace std// Tolerance for testing KKT conditions.
#define TESTTOL 1e-9
// Tolerance for barrier convergence.
#define CONVTOL 1e-9//  A Simple Example//  Minimize//   obj: x1 + x2 + x3 + x4 + x5 + x6//  Subject To//   c1: x1 + x2      + x5      = 8//   c2:           x3 + x5 + x6 = 10//   q1: x1 >= |(x2, x3)| ---->>>>  q1: [ -x1^2 + x2^2 + x3^2 ] <= 0 and x1 >=0//   q2: x4 >= |x5|       ---->>>>  q2: [ -x4^2 + x5^2 ] <= 0 and x4 >=0//  Bounds//   x2 Free//   x3 Free//   x5 Free//   x6 Free//  Endstatic void
createmodel(IloModel& model, IloObjective &obj, IloNumVarArray &x,IloRangeArray &rngs, IloIntArray& cone)
{IloEnv env = model.getEnv();// Create variables.x.add(IloNumVar(env, 0, IloInfinity));x.add(IloNumVar(env, -IloInfinity, IloInfinity));x.add(IloNumVar(env, -IloInfinity, IloInfinity));x.add(IloNumVar(env, 0, IloInfinity));x.add(IloNumVar(env, -IloInfinity, IloInfinity));x.add(IloNumVar(env, -IloInfinity, IloInfinity));// Create objective function and immediately store it in return value.// obj = IloMinimize(env, x1 + x2 + x3 + x4 + x5 + x6);obj = IloMinimize(env, x[0]+x[1] + x[2] + x[3] + x[4] + x[5]);// Setup model.model.add(x[0] + x[1] + x[4]==8);model.add(x[2] + x[4] + x[5]==10);model.add(-x[0] * x[0] + x[1] * x[1] + x[2] * x[2]<=0);//equal to model.add(-x[3] * x[3] + x[4] * x[4]<=0), useful for lots of variablesdouble a[] = {0,0,0, -1,1 };IloExpr temp(env);for (IloInt i = 3; i < 5; i++){temp += a[i] * x[i] * x[i];}model.add(temp <= 0);temp.end();model.add(obj);
}int
main(void)
{IloEnv env;int retval = -1;try {// Create the model.IloModel model(env);IloCplex cplex(env);IloObjective obj(env);IloNumVarArray vars(env);IloRangeArray rngs(env);IloIntArray cone(env);createmodel(model, obj, vars, rngs, cone);// Extract model.cplex.extract(model);// Solve the problem. If we cannot find an _optimal_ solution then// there is no point in checking the KKT conditions and we throw an// exception.cplex.setParam(IloCplex::Param::Barrier::QCPConvergeTol, CONVTOL);if (!cplex.solve() || cplex.getStatus() != IloAlgorithm::Optimal)throw string("Failed to solve problem to optimality");IloNumArray vals_x(env);env.out() << "Solution status = " << cplex.getStatus() << endl;env.out() << "Solution value  = " << cplex.getObjValue() << endl;cplex.getValues(vals_x, vars);env.out() << "Values        = " << vals_x << endl;env.end();}catch (IloException &e) {cerr << "IloException: " << e << endl;if (env.getImpl())env.end();::abort();}catch (string& e) {cerr << e << endl;if (env.getImpl())env.end();::abort();}return retval;
}

运行结果如下图:
在这里插入图片描述

一个更一般的例子

在前面例子的基础上,我们只是改变了约束q1,使其更一般化,如下图所示:
在这里插入图片描述

为了将q1转化为合适的格式,我们使用变量替换 $x_7=x_1+x_2 $ 。因此只需在前面源代码中更改 createmodel 函数中的部分代码。为保持代码完整性,我们依旧给出完整的代码:

#include <cmath>
#include <string>
#include <iostream>
#include <ilcplex/ilocplex.h>ILOSTLBEGIN // import namespace std// Tolerance for testing KKT conditions.
#define TESTTOL 1e-9
// Tolerance for barrier convergence.
#define CONVTOL 1e-9//  A Simple Example//  Minimize//   obj: x1 + x2 + x3 + x4 + x5 + x6//  Subject To//   c1: x1 + x2      + x5      = 8//   c2:           x3 + x5 + x6 = 10//   q1: x1 + x2 >= |(x1, x2, x3)| ---->>>> q1:[-x7^2+x1^2+x2^2+x3^2]<=0 and x7=x1+x2>=0//   q2: x4 >= |x5|       ---->>>>  q2: [ -x4^2 + x5^2 ] <= 0 and x4 >=0//  Bounds//   x1 Free//   x2 Free//   x3 Free//   x5 Free//   x6 Free//  Endstatic void
createmodel(IloModel& model, IloObjective &obj, IloNumVarArray &x,IloRangeArray &rngs, IloIntArray& cone)
{IloEnv env = model.getEnv();// Create variables.x.add(IloNumVar(env, -IloInfinity, IloInfinity));x.add(IloNumVar(env, -IloInfinity, IloInfinity));x.add(IloNumVar(env, -IloInfinity, IloInfinity));x.add(IloNumVar(env, 0, IloInfinity));x.add(IloNumVar(env, -IloInfinity, IloInfinity));x.add(IloNumVar(env, -IloInfinity, IloInfinity));x.add(IloNumVar(env, 0, IloInfinity));// x7// Create objective function and immediately store it in return value.// obj = IloMinimize(env, x1 + x2 + x3 + x4 + x5 + x6);obj = IloMinimize(env, x[0]+x[1] + x[2] + x[3] + x[4] + x[5]);// Setup model.model.add(x[0] + x[1] + x[4]==8);model.add(x[2] + x[4] + x[5]==10);model.add(x[6] - x[0] - x[1] == 0); // x7 = x1 + x2model.add(-x[6] * x[6]+ x[0] * x[0] + x[1] * x[1] + x[2] * x[2]<=0); //[-x7^2+x1^2+x2^2+x3^2]<=0//equal to model.add(-x[3] * x[3] + x[4] * x[4]<=0), useful for lots of variablesdouble a[] = {0,0,0, -1,1 };IloExpr temp(env);for (IloInt i = 3; i < 5; i++){temp += a[i] * x[i] * x[i];}model.add(temp <= 0);temp.end();model.add(obj);
}int
main(void)
{IloEnv env;int retval = -1;try {// Create the model.IloModel model(env);IloCplex cplex(env);IloObjective obj(env);IloNumVarArray vars(env);IloRangeArray rngs(env);IloIntArray cone(env);createmodel(model, obj, vars, rngs, cone);// Extract model.cplex.extract(model);// Solve the problem. If we cannot find an _optimal_ solution then// there is no point in checking the KKT conditions and we throw an// exception.cplex.setParam(IloCplex::Param::Barrier::QCPConvergeTol, CONVTOL);if (!cplex.solve() || cplex.getStatus() != IloAlgorithm::Optimal)throw string("Failed to solve problem to optimality");IloNumArray vals_x(env);env.out() << "Solution status = " << cplex.getStatus() << endl;env.out() << "Solution value  = " << cplex.getObjValue() << endl;cplex.getValues(vals_x, vars);env.out() << "Values        = " << vals_x << endl;env.end();}catch (IloException &e) {cerr << "IloException: " << e << endl;if (env.getImpl())env.end();::abort();}catch (string& e) {cerr << e << endl;if (env.getImpl())env.end();::abort();}return retval;
}

运行结果如下图:
在这里插入图片描述

这篇关于【漫漫科研路\CC++】CPLEX解SOCP问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/841948

相关文章

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

SpringBoot启动报错的11个高频问题排查与解决终极指南

《SpringBoot启动报错的11个高频问题排查与解决终极指南》这篇文章主要为大家详细介绍了SpringBoot启动报错的11个高频问题的排查与解决,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一... 目录1. 依赖冲突:NoSuchMethodError 的终极解法2. Bean注入失败:No qu

MySQL新增字段后Java实体未更新的潜在问题与解决方案

《MySQL新增字段后Java实体未更新的潜在问题与解决方案》在Java+MySQL的开发中,我们通常使用ORM框架来映射数据库表与Java对象,但有时候,数据库表结构变更(如新增字段)后,开发人员可... 目录引言1. 问题背景:数据库与 Java 实体不同步1.1 常见场景1.2 示例代码2. 不同操作

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa

如何解决mysql出现Incorrect string value for column ‘表项‘ at row 1错误问题

《如何解决mysql出现Incorrectstringvalueforcolumn‘表项‘atrow1错误问题》:本文主要介绍如何解决mysql出现Incorrectstringv... 目录mysql出现Incorrect string value for column ‘表项‘ at row 1错误报错

如何解决Spring MVC中响应乱码问题

《如何解决SpringMVC中响应乱码问题》:本文主要介绍如何解决SpringMVC中响应乱码问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring MVC最新响应中乱码解决方式以前的解决办法这是比较通用的一种方法总结Spring MVC最新响应中乱码解

pip无法安装osgeo失败的问题解决

《pip无法安装osgeo失败的问题解决》本文主要介绍了pip无法安装osgeo失败的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 进入官方提供的扩展包下载网站寻找版本适配的whl文件注意:要选择cp(python版本)和你py

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa