整数线性规划求解工具isl使用方法

整数线性规划求解工具isl使用方法整数线性规划求解工具 Integer Set Library 代码 参考 isl 是一个用于多面体模型调度实现的 c c 库 通过 isl 我们可以对模型进行自动的调度 循环优化等 编译 ISL Integer Set Library 版本 0 22 1 http isl gforge inria fr

大家好,我是讯享网,很高兴认识大家。

整数线性规划求解工具 Integer Set Library

代码

参考

isl是一个用于多面体模型调度实现的c/c++库。通过isl,我们可以对模型进行自动的调度,循环优化等。

编译

ISL,Integer Set Library 版本0.22.1,http://isl.gforge.inria.fr/ README关于编译的部分说了 ./configure make make install 使用./configure --help阅读后针对本地环境,使用 ./configure --prefix=/opt/isl --enable-shared=yes --enable-static=yes \ CC=/opt/gcc/bin/gcc \ CFLAGS="-O3 -I/opt/gmp/include" \ LDFLAGS="-L/opt/gmp/lib -Wl,--rpath=/opt/gmp/lib" \ CXX=/opt/gcc-10.2.0/bin/g++ \ CXXFLAGS="-I/opt/gmp/include" \ PYTHON=/opt/python3/bin/python3 \ --enable-fast-install=no --with-gnu-ld make make install 

讯享网

islpy python接口

isl内部对象介绍

  • 1.isl_ctx对象的创建(初始化):

整数集和关系的所有操作都在的上下文中发生isl_ctx。给定isl_ctx只能在单个线程中使用。一个函数的所有参数都必须在同一上下文中分配。当前没有功能可用于将对象从一个移动isl_ctx到另一个isl_ctx。这意味着当前无法安全地将对象从一个线程移动到另一个线程,除非整个线程isl_ctx都移动了。

一个isl_ctx可以使用分配isl_ctx_alloc和使用中解脱出来isl_ctx_free。在isl_ctx释放之前,应释放内分配的所有对象isl_ctx。

isl_ctx 对象就像一根线一样把上下文关系(对象)连接起来。

讯享网isl_ctx *isl_ctx_alloc(); void isl_ctx_free(isl_ctx *ctx); 

测试:

isl_ctx *isl = isl_ctx_alloc(); // 创建对象 cout << isl << endl; isl_ctx_free(isl); // 释放 

输出是一个地址值,可以看出来该指针指向一个对象。

同时,我们还可以为 isl_ctx 对象指定低级 op 数量的范围(bound)。例如:

讯享网void isl_ctx_set_max_operations(isl_ctx *ctx, unsigned long max_operations); unsigned long isl_ctx_get_max_operations(isl_ctx *ctx); void isl_ctx_reset_operations(isl_ctx *ctx); 

上面说了ctx相当于线将各种对象连接起来,那么我们还可以通过上下文对象来得到ctx:

#include <isl/val.h> isl_ctx *isl_val_get_ctx(__isl_keep isl_val *val); isl_ctx *isl_multi_val_get_ctx( __isl_keep isl_multi_val *mv); #include <isl/id.h> isl_ctx *isl_id_get_ctx(__isl_keep isl_id *id); isl_ctx *isl_multi_id_get_ctx( __isl_keep isl_multi_id *mi); #include <isl/local_space.h> isl_ctx *isl_local_space_get_ctx( __isl_keep isl_local_space *ls); #include <isl/set.h> isl_ctx *isl_set_list_get_ctx( __isl_keep isl_set_list *list); #include <isl/aff.h> isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff); isl_ctx *isl_multi_aff_get_ctx( __isl_keep isl_multi_aff *maff); isl_ctx *isl_pw_aff_get_ctx(__isl_keep isl_pw_aff *pa); isl_ctx *isl_pw_multi_aff_get_ctx( __isl_keep isl_pw_multi_aff *pma); isl_ctx *isl_multi_pw_aff_get_ctx( __isl_keep isl_multi_pw_aff *mpa); isl_ctx *isl_union_pw_aff_get_ctx( __isl_keep isl_union_pw_aff *upa); isl_ctx *isl_union_pw_multi_aff_get_ctx( __isl_keep isl_union_pw_multi_aff *upma); isl_ctx *isl_multi_union_pw_aff_get_ctx( __isl_keep isl_multi_union_pw_aff *mupa); #include <isl/id_to_ast_expr.h> isl_ctx *isl_id_to_ast_expr_get_ctx( __isl_keep isl_id_to_ast_expr *id2expr); #include <isl/point.h> isl_ctx *isl_point_get_ctx(__isl_keep isl_point *pnt); #include <isl/vec.h> isl_ctx *isl_vec_get_ctx(__isl_keep isl_vec *vec); #include <isl/mat.h> isl_ctx *isl_mat_get_ctx(__isl_keep isl_mat *mat); #include <isl/vertices.h> isl_ctx *isl_vertices_get_ctx( __isl_keep isl_vertices *vertices); isl_ctx *isl_vertex_get_ctx(__isl_keep isl_vertex *vertex); isl_ctx *isl_cell_get_ctx(__isl_keep isl_cell *cell); #include <isl/flow.h> isl_ctx *isl_restriction_get_ctx( __isl_keep isl_restriction *restr); isl_ctx *isl_union_access_info_get_ctx( __isl_keep isl_union_access_info *access); isl_ctx *isl_union_flow_get_ctx( __isl_keep isl_union_flow *flow); #include <isl/schedule.h> isl_ctx *isl_schedule_get_ctx( __isl_keep isl_schedule *sched); isl_ctx *isl_schedule_constraints_get_ctx( __isl_keep isl_schedule_constraints *sc); #include <isl/schedule_node.h> isl_ctx *isl_schedule_node_get_ctx( __isl_keep isl_schedule_node *node); #include <isl/ast_build.h> isl_ctx *isl_ast_build_get_ctx( __isl_keep isl_ast_build *build); #include <isl/ast.h> isl_ctx *isl_ast_expr_get_ctx( __isl_keep isl_ast_expr *expr); isl_ctx *isl_ast_node_get_ctx( __isl_keep isl_ast_node *node); #include <isl/stride_info.h> isl_ctx *isl_stride_info_get_ctx( __isl_keep isl_stride_info *si); #include <isl/fixed_box.h> isl_ctx *isl_fixed_box_get_ctx( __isl_keep isl_fixed_box *box); 
  • 2.返回的结果

isl isl_size对返回非负值(通常是数字或位置)的函数使用特殊的返回类型。除了常规的非负返回值外,isl_size_error还可能返回一个特殊的(负)值,表明出错。

isl对于返回布尔值或原则上不返回任何值的函数,它也使用两种特殊的返回类型。特别是,该isl_bool类型具有三个可能的值:(isl_bool_true一个正整数),表示true或yes;isl_bool_false(整数值零),表示false或no;和isl_bool_error(负整数值),表示出了点问题。在上定义了以下操作isl_bool。该函数isl_bool_not可以被用于否定的isl_bool,其中的否定isl_bool_error是isl_bool_error一次。该函数isl_bool_ok将整数转换为isl_bool。任何非零值的收益率isl_bool_true和零收益率isl_bool_false。

讯享网bool int a = 0; isl_bool result = isl_bool_ok(a); cout << result << endl; 

输出结果为0

  • 3.isl_val对象

一个 isl_val 对象表示整数值,有理值或三个特殊值之一,即无穷大,负无穷大和正无穷大。可以使用以下功能创建一些预定义的值:

#include <isl/val.h> __isl_give isl_val *isl_val_zero(isl_ctx *ctx); __isl_give isl_val *isl_val_one(isl_ctx *ctx); __isl_give isl_val *isl_val_negone(isl_ctx *ctx); __isl_give isl_val *isl_val_nan(isl_ctx *ctx); __isl_give isl_val *isl_val_infty(isl_ctx *ctx); __isl_give isl_val *isl_val_neginfty(isl_ctx *ctx); 

测试:

讯享网isl_val * val = isl_val_zero(isl); cout << val << endl; 

输出:

0x93c6080

可以使用以下函数创建特定的整数值:

#include <isl/val.h> __isl_give isl_val *isl_val_int_from_si(isl_ctx *ctx, long i); __isl_give isl_val *isl_val_int_from_ui(isl_ctx *ctx, unsigned long u); __isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, size_t n, size_t size, const void *chunks); 

一个isl_val可以使用下面的函数来修改:

讯享网#include <isl/val.h> __isl_give isl_val *isl_val_set_si(__isl_take isl_val *v, long i); 

可以使用以下功能复制和释放 isl_val 。

#include <isl/val.h> __isl_give isl_val *isl_val_copy(__isl_keep isl_val *v); __isl_null isl_val *isl_val_free(__isl_take isl_val *v); 

对于这样的数值对象我们还可以对其进行一元运算、二元运算等,具体运算函数可以参考文档。

  • 3.集合(set)与关系或映射(map)

isl使用六种类型的代表集合和关系的对象,

isl_basic_set,

isl_basic_map,

isl_set,

isl_map,

isl_union_set 和

isl_union_map(这些其实都是对象)。

isl_basic_set和isl_basic_map分别代表可仿射约束的集合和关系,而isl_set和isl_map分别代表isl_basic_sets和isl_basic_maps 的并集。但是,所有isl_basic_sets或isl_basic_maps都必须居住在同一空间中。isl_union_sets和isl_union_maps表示isl_sets或isl_maps在不同空间中的并集,如果空间的维数和/或名称不同,则它们被认为是不同的(请参见“空间”)。集和关系(映射)之间的区别在于,set具有一组变量,而map具有两组变量,即输入变量和输出变量。

  • 4.错误处理

isl在触发运行时错误时,支持不同的反应方式。例如,如果isl_map_intersect用两个具有不兼容空间的映射调用诸如之类的函数,则会出现运行时错误。有三种对错误做出反应的方式:警告,继续或中止。

默认行为是警告。在这种模式下,isl打印警告,将最后一个错误存储在相应isl_ctx的错误中,触发错误的函数将返回一个值,指示发生了某些错误。如果函数返回指针,则该值为NULL。在返回一个功能的情况下isl_size,isl_bool或者isl_stat,这个值isl_size_error,isl_bool_error或isl_stat_error。错误不会破坏内部状态,因此可以继续使用isl。isl还提供了读取上一个错误的功能,包括特定的错误消息,发生错误的isl源文件和行号,以及重置有关上一个错误的所有信息。最后的错误仅用于提供信息。它的存在不会改变的行为isl。因此,重新设置错误并不需要继续使用isl,而只是为了观察新的错误。

  • 5.isl_id对象

标识符用于识别单个维度和维度元组。它们由一个可选的名称和一个可选的用户指针(代表该id对象标识哪个对象)组成。但是,名称和用户指针不能都为NULL。具有相同名称但指针值不同的标识符被认为是不同的。同样,具有不同名称但指针值相同的标识符也被认为是不同的。相同的标识符使用相同的对象表示。因此,可以使用==运算符测试成对的标识符是否相等。可以使用以下功能构造,复制,释放,检查和打印标识符。

讯享网#include <isl/id.h> __isl_give isl_id *isl_id_alloc(isl_ctx *ctx, __isl_keep const char *name, void *user); __isl_give isl_id *isl_id_set_free_user( __isl_take isl_id *id, void (*free_user)(void *user)); __isl_give isl_id *isl_id_copy(isl_id *id); __isl_null isl_id *isl_id_free(__isl_take isl_id *id); void *isl_id_get_user(__isl_keep isl_id *id); __isl_keep const char *isl_id_get_name(__isl_keep isl_id *id); __isl_give isl_printer *isl_printer_print_id( __isl_take isl_printer *p, __isl_keep isl_id *id); 

使用示例:

isl_set *sum = isl_set_sum(set, set2); // 表示对set、set2这两个集合对象进行加法 isl_id *ids = isl_id_alloc(ctx, "sum", sum);// 定义一个id指向sum char *str_id = isl_id_to_str(ids); printf("id:%s\n", str_id); 

最后输出如下,代表一个地址值:


讯享网

id:sum@0x993a9e0

  • 6.isl_space对象

每当从头开始创建新的set,map或类似对象时,都需要使用来指定其所处的空间isl_space。

每个空间包含零个或多个参数,以及零个,一个或两个元组的 set 或输入/输出维。参数和尺寸由isl_dim_type和标识。类型isl_dim_param是指参数,类型isl_dim_set是指设置维(对于具有单个元组的空间)和类型isl_dim_in,而类型isl_dim_out是指输入和输出维(对于具有两个元组的空间)。局部空间也包含类型的尺寸isl_dim_div。注意,参数仅由其在给定对象中的位置来标识。在不同的对象之间,参数(通常)由其名称或标识符标识。只有未命名的参数才能通过它们在对象之间的位置来标识。不建议使用未命名的参数。

对space的基本操作如下:

讯享网#include <isl/space.h> __isl_give isl_space *isl_space_unit(isl_ctx *ctx); __isl_give isl_space *isl_space_alloc(isl_ctx *ctx, unsigned nparam, unsigned n_in, unsigned n_out);//带进带出的专用于map __isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx, unsigned nparam); __isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx, unsigned nparam, unsigned dim); __isl_give isl_space *isl_space_copy(__isl_keep isl_space *space); __isl_null isl_space *isl_space_free(__isl_take isl_space *space); 

需要使用isl_space_unit或创建用于创建参数域的空间isl_space_params_alloc。对于其他集合,需要使用来创建空间isl_space_set_alloc,而对于关系而言,需要使用来创建空间isl_space_alloc。使用的isl_space_params_alloc,isl_space_set_alloc并且isl_space_alloc因为它们允许引进未命名参数是不鼓励。

要检查给定空间是集合空间还是映射空间,还是参数空间,请使用以下函数:

#include <isl/space.h> isl_bool isl_space_is_params(__isl_keep isl_space *space); isl_bool isl_space_is_set(__isl_keep isl_space *space); isl_bool isl_space_is_map(__isl_keep isl_space *space); 

创建与其他对象位于同一空间的对象通常很有用。这可以通过基于原始对象的空间来创建新对象(请参见“创建新的集合和关系”或“函数”)来完成。

创建和一个多面体对象相同space的space:

讯享网#include <isl/polynomial.h> isl_space *isl_qpolynomial_get_domain_space(isl_qpolynomial *qp); isl_space *isl_qpolynomial_get_space(isl_qpolynomial *qp); isl_space *isl_qpolynomial_fold_get_domain_space( __isl_keep isl_qpolynomial_fold *fold); __isl_give isl_space *isl_qpolynomial_fold_get_space( __isl_keep isl_qpolynomial_fold *fold); __isl_give isl_space *isl_pw_qpolynomial_get_domain_space( __isl_keep isl_pw_qpolynomial *pwqp); __isl_give isl_space *isl_pw_qpolynomial_get_space( __isl_keep isl_pw_qpolynomial *pwqp); __isl_give isl_space *isl_pw_qpolynomial_fold_get_domain_space( __isl_keep isl_pw_qpolynomial_fold *pwf); __isl_give isl_space *isl_pw_qpolynomial_fold_get_space( __isl_keep isl_pw_qpolynomial_fold *pwf); __isl_give isl_space *isl_union_pw_qpolynomial_get_space( __isl_keep isl_union_pw_qpolynomial *upwqp); __isl_give isl_space *isl_union_pw_qpolynomial_fold_get_space( __isl_keep isl_union_pw_qpolynomial_fold *upwf); 

可以使用以下功能将其他参数添加到空间。

#include <isl/space.h> __isl_give isl_space *isl_space_add_param_id( __isl_take isl_space *space, __isl_take isl_id *id); 

相反,可以使用以下函数从空格中删除所有参数。

讯享网#include <isl/space.h> __isl_give isl_space *isl_space_drop_all_params( __isl_take isl_space *space); 

isl基本操作

  • 1.create set & map
    • Empty sets and relations

可以看出来。set和map的创建时凭借于space的。

__isl_give isl_basic_set *isl_basic_set_empty( __isl_take isl_space *space);//创建一个空的set空间 __isl_give isl_basic_map *isl_basic_map_empty( __isl_take isl_space *space); __isl_give isl_set *isl_set_empty( __isl_take isl_space *space); __isl_give isl_map *isl_map_empty( __isl_take isl_space *space); __isl_give isl_union_set *isl_union_set_empty( __isl_take isl_space *space); __isl_give isl_union_map *isl_union_map_empty( __isl_take isl_space *space); 

Universe sets and relations

讯享网_isl_give isl_basic_set *isl_basic_set_universe( __isl_take isl_space *space); __isl_give isl_basic_map *isl_basic_map_universe( __isl_take isl_space *space); __isl_give isl_set *isl_set_universe( __isl_take isl_space *space); __isl_give isl_map *isl_map_universe( __isl_take isl_space *space); __isl_give isl_union_set *isl_union_set_universe( __isl_take isl_union_set *uset); __isl_give isl_union_map *isl_union_map_universe( __isl_take isl_union_map *umap); 

Identity relations

__isl_give isl_basic_map *isl_basic_map_identity( __isl_take isl_space *space); __isl_give isl_map *isl_map_identity( __isl_take isl_space *space); 

可以使用以下功能将基本集合或关系转换为集合或关系:

讯享网__isl_give isl_set *isl_set_from_basic_set( __isl_take isl_basic_set *bset); __isl_give isl_map *isl_map_from_basic_map( __isl_take isl_basic_map *bmap); 

例如,要创建一个包含10到42之间的偶数整数的集合,可以使用以下代码。

isl_space *space; isl_local_space *ls; isl_constraint *c; isl_basic_set *bset; space = isl_space_set_alloc(ctx, 0, 2); bset = isl_basic_set_universe(isl_space_copy(space)); ls = isl_local_space_from_space(space); c = isl_constraint_alloc_equality(isl_local_space_copy(ls)); c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 2); bset = isl_basic_set_add_constraint(bset, c); c = isl_constraint_alloc_inequality(isl_local_space_copy(ls)); c = isl_constraint_set_constant_si(c, -10); c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1); bset = isl_basic_set_add_constraint(bset, c); c = isl_constraint_alloc_inequality(ls); c = isl_constraint_set_constant_si(c, 42); c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1); bset = isl_basic_set_add_constraint(bset, c); bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 1); 

或者:

讯享网isl_basic_set *bset; bset = isl_basic_set_read_from_str(ctx, "{[i] : exists (a : i = 2a and i >= 10 and i <= 42)}"); 

整体程序如下:

int main() { 
    isl_ctx *ctx = isl_ctx_alloc(); isl_basic_set *bset; bset = isl_basic_set_read_from_str(ctx, "{[i] : exists (a : i = 2a and i >= 10 and i <= 42)}"); const char *out = isl_basic_set_to_str(bset); cout << out << endl; return 0; } 

最终输出:

{ [i] : (i) mod 2 = 0 and 10 <= i <= 42 }

这便是一个最简单的调度编写,这种语法表示 i 是一个循环变量,接下来我们看一下,如何能从字符串创建相应的 set、map 等对象。

2.Input & output

对于集合和关系,isl支持其自己的输入/输出格式,该格式类似于该Omega格式,但PolyLib在某些情况下还支持该格式。对于其他对象类型,通常仅isl支持一种格式。

输入

例如从输入格式创建一个basic_set对象:

讯享网#include <stdio.h> #include <isl/ctx.h> #include <isl/set.h> using namespace std; int main() { isl_ctx *ctx = isl_ctx_alloc();//create a ctx object isl_basic_set *bset; bset = isl_basic_set_read_from_str(ctx, "[n] -> { [i] : exists (a = [i/10] : 0 <= i and i <= n and i - 10 a <= 6) }"); //表示 i % 10 <= 6 char *out = isl_basic_set_to_str(bset); printf("%s\n", out); isl_basic_set_free(bset); isl_ctx_free(ctx); return 0; } 

输出结果:

n -> { [i] : 0 <= i <= n and 10*floor((3 + i)/10) <= i }

floor表示向下取整,可以看到isl帮我们把这样的循环变量进行了一些微调。

我们还可以使用以下的函数来从特定的输入格式创建相应对象:

#include <isl/id.h> __isl_give isl_id *isl_id_read_from_str(isl_ctx *ctx, const char *str);//创建id对象 __isl_give isl_multi_id *isl_multi_id_read_from_str( isl_ctx *ctx, const char *str); #include <isl/val.h> __isl_give isl_val *isl_val_read_from_str(isl_ctx *ctx, const char *str);//创建一个val对象 __isl_give isl_multi_val *isl_multi_val_read_from_str( isl_ctx *ctx, const char *str); #include <isl/set.h> __isl_give isl_basic_set *isl_basic_set_read_from_file( isl_ctx *ctx, FILE *input); __isl_give isl_basic_set *isl_basic_set_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_set *isl_set_read_from_file(isl_ctx *ctx, FILE *input); __isl_give isl_set *isl_set_read_from_str(isl_ctx *ctx, const char *str); #include <isl/map.h> __isl_give isl_basic_map *isl_basic_map_read_from_file( isl_ctx *ctx, FILE *input); __isl_give isl_basic_map *isl_basic_map_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_map *isl_map_read_from_file( isl_ctx *ctx, FILE *input); __isl_give isl_map *isl_map_read_from_str(isl_ctx *ctx, const char *str); #include <isl/union_set.h> __isl_give isl_union_set *isl_union_set_read_from_file( isl_ctx *ctx, FILE *input); __isl_give isl_union_set *isl_union_set_read_from_str( isl_ctx *ctx, const char *str); #include <isl/union_map.h> __isl_give isl_union_map *isl_union_map_read_from_file( isl_ctx *ctx, FILE *input); __isl_give isl_union_map *isl_union_map_read_from_str( isl_ctx *ctx, const char *str); #include <isl/aff.h> __isl_give isl_aff *isl_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_multi_aff *isl_multi_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_pw_aff *isl_pw_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_multi_pw_aff *isl_multi_pw_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_union_pw_aff * isl_union_pw_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_union_pw_multi_aff * isl_union_pw_multi_aff_read_from_str( isl_ctx *ctx, const char *str); __isl_give isl_multi_union_pw_aff * isl_multi_union_pw_aff_read_from_str( isl_ctx *ctx, const char *str); #include <isl/polynomial.h> __isl_give isl_union_pw_qpolynomial * isl_union_pw_qpolynomial_read_from_str( isl_ctx *ctx, const char *str); 

输出

在可以打印任何内容之前,需要先创建一个isl_printer对象:

讯享网__isl_give isl_printer *isl_printer_to_file(isl_ctx *ctx, FILE *file); __isl_give isl_printer *isl_printer_to_str(isl_ctx *ctx); __isl_null isl_printer *isl_printer_free( __isl_take isl_printer *printer); 

isl_printer_to_file打印到给定的文件,同时isl_printer_to_str打印到可以使用以下函数提取的字符串。

#include <isl/printer.h> __isl_give char *isl_printer_get_str( __isl_keep isl_printer *printer); 

还是刚才的程序,我们继续用isl_printer对象来输出:

讯享网int main() { 
    isl_ctx *ctx = isl_ctx_alloc();//create a ctx object isl_basic_set *bset; bset = isl_basic_set_read_from_str(ctx, "[n] -> { [i] : exists (a = [i/10] : 0 <= i and i <= n and i - 10 a <= 6) }"); char *out = isl_basic_set_to_str(bset); printf("%s\n", out); isl_printer *p = isl_printer_to_str(ctx); p = isl_printer_print_basic_set(p, bset); //表示输出basic_set char *out2 = isl_printer_get_str(p); printf("%s", out2); isl_printer_free(p); isl_basic_set_free(bset); isl_ctx_free(ctx); return 0; } 

输出结果为两行一样的循环变量约束:

n -> { [i] : 0 <= i <= n and 10floor((3 + i)/10) <= i }
n -> { [i] : 0 <= i <= n and 10
floor((3 + i)/10) <= i }

另外,可以使用以下函数直接获取字符串表示形式,该函数始终以isl格式打印:

#include <isl/space.h> __isl_give char *isl_space_to_str( __isl_keep isl_space *space); #include <isl/val.h> __isl_give char *isl_val_to_str(__isl_keep isl_val *v); __isl_give char *isl_multi_val_to_str( __isl_keep isl_multi_val *mv); #include <isl/set.h> __isl_give char *isl_basic_set_to_str( __isl_keep isl_basic_set *bset); __isl_give char *isl_set_to_str( __isl_keep isl_set *set); #include <isl/union_set.h> __isl_give char *isl_union_set_to_str( __isl_keep isl_union_set *uset); #include <isl/map.h> __isl_give char *isl_basic_map_to_str( __isl_keep isl_basic_map *bmap); __isl_give char *isl_map_to_str( __isl_keep isl_map *map); #include <isl/union_map.h> __isl_give char *isl_union_map_to_str( __isl_keep isl_union_map *umap); 
小讯
上一篇 2025-04-05 10:30
下一篇 2025-03-31 23:34

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/117431.html