Flat White Vitriol - An incremental solver protocol for combinatorial solving using shared objects

refactor: rename interface to FZnSO

dekker.one 72de4f05 b3cc2de5

verified
+1445 -1224
+2 -2
Cargo.toml
··· 1 1 [workspace] 2 2 3 - members = ["rust/ipdos-solver-template","rust/ipdos-types"] 3 + members = ["rust/fznso","rust/fznso-solver-template","rust/fznso-types"] 4 4 5 5 resolver = "2" 6 6 7 7 [workspace.package] 8 - repository = "https://tangled.sh/@dekker.one/ipdos" 8 + repository = "https://tangled.org/dekker.one/FZnSO" 9 9 version = "0.1.0" 10 10 authors = ["Jip J. Dekker <jip@dekker.one>"] 11 11 edition = "2024"
+3 -3
Justfile
··· 1 1 default: build check 2 2 3 - # Build the Huub solver 3 + # Build packages and header files 4 4 build: 5 5 cargo build 6 - cbindgen --config cbindgen_types.toml --crate ipdos-types --output c/ipdos_types.h 7 - cbindgen --config cbindgen_template.toml --crate ipdos-solver-template --output c/ipdos_solver_template.c 6 + cbindgen --config cbindgen_types.toml --crate fznso-types --output c/fznso_types.h 7 + cbindgen --config cbindgen_template.toml --crate fznso-solver-template --output c/fznso_solver_template.c 8 8 9 9 # Check the codebase using all CI linters 10 10 check:
+6 -6
README.md
··· 1 - # IPDOS: An Incremental Protocol for Decision and Optimization Solvers 1 + # Flat White Vitriol (FZnSO) - An incremental solver protocol for combinatorial solving using shared objects 2 2 3 3 ## Introduction 4 4 5 5 ## Common Functionality 6 6 7 - Although solvers are able to define their own functionality using the IPDOS protocol, we advocate for the following common functionality to be implemented by different solvers. 7 + Although solvers are able to define their own functionality using the FZnSO protocol, we advocate for the following common functionality to be implemented by different solvers. 8 8 This will allow for a more consistent user experience when interacting with different solvers. 9 9 Even if a solver does not implement all of these functions, we recommend that the solvers do not use the same name for different functionality. 10 10 11 11 ### Common Options 12 12 13 - A solver will expose its available options through `ipdos_option_list`. 13 + A solver will expose its available options through `fznso_option_list`. 14 14 We recommend that solvers eagerly implement the following options: 15 15 16 16 - `all_optimal` (`bool`, default: `false`): If set to `true`, the solver will after finding an optimal solution, continue to search for other solutions with the same objective value. 17 17 - `fixed_search` (`bool`, default: `false`): If set to `true`, the solver will strictly follow the search order defined by the user. 18 18 - `intermediate` (`bool`, default: `false`): If set to `true` for a problem with an objective strategy set, the solver will trigger its `on_solution` callback when it finds an intermediate solution. 19 - Afterward, the solver will continue the search until it finds the next solution, or it proves that no better solutions exist (returning the `IpdosComplete` status). 19 + Afterward, the solver will continue the search until it finds the next solution, or it proves that no better solutions exist (returning the `FznsoComplete` status). 20 20 - `threads` (`int`, default: `1`): For multithreaded solvers, this option will set the number of threads to use. 21 21 - `time_limit` (`int`, default: `-1`): If set to a positive integer, the solver will abandon the search after the specified number of milliseconds. 22 22 - `random_seed` (`opt int`, default: `<>`): If set to a positive integer, the solver will use the given value as the seed for its random number generator. ··· 25 25 26 26 ### Common Constraints 27 27 28 - A solver will expose the constraints that can be used in a `IpdosModel` through `ipdos_constraint_list`. 28 + A solver will expose the constraints that can be used in a `FznsoModel` through `fznso_constraint_list`. 29 29 We encourage solvers to support the constraints using the names and definitions from the [FlatZinc Builtins](https://docs.minizinc.dev/en/stable/lib-flatzinc.html). 30 30 Other MiniZinc (global) constraints are also encouraged to be implemented, using the `fzn_` prefix. 31 31 32 32 ### Common Objective Strategies 33 33 34 - A solver will expose the objective strategies that can be used in a `IpdosModel` through `ipdos_objective_list`. 34 + A solver will expose the objective strategies that can be used in a `FznsoModel` through `fznso_objective_list`. 35 35 We encourage solvers to support the following objective strategies if possible: 36 36 37 37 - `lex_maximize_int` (`list of var int`) | `lex_maximize_float` (`list of var float`): The solver will maximize the list of decision variables in lexicographical order, i.e., the first variable is maximized first, then the second variable, etc.
+507
c/fznso_types.h
··· 1 + #ifndef fznso_types_h 2 + #define fznso_types_h 3 + 4 + #include <stdbool.h> 5 + #include <stdint.h> 6 + 7 + // Representation of the base type of a value. 8 + typedef enum FznsoTypeBase { 9 + // Boolean type 10 + FznsoTypeBaseBool, 11 + // Integer numeric type 12 + FznsoTypeBaseInt, 13 + // Floating point numeric type 14 + FznsoTypeBaseFloat, 15 + // Character string type 16 + FznsoTypeBaseString, 17 + } FznsoTypeBase; 18 + 19 + // Enumerated type used to mark the kind of [`FznsoValue`]. This is used to 20 + // determine which "get" method in [`FznsoValueMethods`] is safe to call. 21 + typedef enum FznsoValueKind { 22 + // No value is available. 23 + FznsoValueAbsent, 24 + // The value is available using [`FznsoValueMethods::get_decision`]. 25 + FznsoValueDecision, 26 + // The value is available using [`FznsoValueMethods::get_constraint`]. 27 + FznsoValueConstraint, 28 + // The value is available using [`FznsoValueMethods::get_bool`]. 29 + FznsoValueBool, 30 + // The value is available using [`FznsoValueMethods::get_int`]. 31 + FznsoValueInt, 32 + // The value is available using [`FznsoValueMethods::get_float`]. 33 + FznsoValueFloat, 34 + // The value is available using [`FznsoValueMethods::get_string`]. 35 + FznsoValueString, 36 + // Sets of integers are represented using a range list. The number of 37 + // ranges is available using [`FznsoValueMethods::len`], and the ranges can 38 + // be accessed using [`FznsoValueMethods::get_range_int`]. 39 + FznsoValueSetInt, 40 + // Sets of floats are represented using a range list. The number of 41 + // ranges is available using [`FznsoValueMethods::len`], and the ranges can 42 + // be accessed using [`FznsoValueMethods::get_range_float`]. 43 + FznsoValueSetFloat, 44 + // The length of the list can be accessed using 45 + // [`FznsoValueMethods::len`], and elements in the list can be 46 + // accessed using [`FznsoValueMethods::get_element`] 47 + FznsoValueList, 48 + } FznsoValueKind; 49 + 50 + // The status returned by `fznso_solver_run`, indicating whether the solver 51 + // completed its search. 52 + typedef enum FznsoStatus { 53 + // The solver explored the full search space and yielded all relevant 54 + // solutions. 55 + FznsoComplete, 56 + // The solver did not explore the full search space due to a timeout or 57 + // other termination condition. Additional (better) solutions might be 58 + // possible. 59 + FznsoIncomplete, 60 + // An error occurred during the solver's execution. 61 + // 62 + // [`fznso_solver_read_error`] can be used to retrieve the error message. 63 + FznsoError, 64 + } FznsoStatus; 65 + 66 + // The handle to a the data of a solution instance. 67 + // 68 + // This type is opaque to the user. Only pointers of this type are ever used. 69 + // 70 + // In implementation of the FZnSO interface, a pointer is generally cast to 71 + // this type, i.e. `(FznsoSolutionData*) my_solution`. A similar cast can be 72 + // used to cast the pointer back to the original type, e.g. `(MySolution*) 73 + // fznso_solution`. 74 + typedef void FznsoAnnotation; 75 + 76 + // Representation of a type to signal and check whether an argument takes the 77 + // correct type. 78 + typedef struct FznsoType { 79 + // Whether the type is a list of values. 80 + bool list_of; 81 + // Whether the argument can be or contain decision variables (represented 82 + // as decision indexes). 83 + bool decision; 84 + // Whether expected type is an set of values of the base type. 85 + bool set_of; 86 + // Whether the expected type is optional (and can take the value of 87 + // [`FznsoValueKind::FznsoValueAbsent`]). 88 + bool opt; 89 + // The expected base type of the argument. 90 + enum FznsoTypeBase base; 91 + } FznsoType; 92 + 93 + // Representation of a type of constraint, discerned by its identifier and the 94 + // types of its arguments. 95 + typedef struct FznsoConstraintType { 96 + // The identifier of the constraint type. 97 + const char *ident; 98 + // The number of expected arguments for the constraint type. 99 + size_t arg_len; 100 + // The types of the expected arguments for the constraint type. 101 + const struct FznsoType *arg_types; 102 + } FznsoConstraintType; 103 + 104 + // A list of [`FznsoConstraintType`]s. 105 + // 106 + // This type is for example used to return from [`fznso_constraint_list`]. 107 + typedef struct FznsoConstraintList { 108 + // The number of elements in the `constraints` array. 109 + size_t len; 110 + // An array of constraint types. 111 + const struct FznsoConstraintType *constraints; 112 + } FznsoConstraintList; 113 + 114 + // The handle of a model instance. 115 + // 116 + // This type is opaque to the user. Only pointers of this type are ever used. 117 + // 118 + // In implementation of the FZnSO interface, a pointer is generally cast to 119 + // this type, i.e. `(FznsoModelData*) my_model`. A similar cast can be used to 120 + // cast the pointer back to the original type, e.g. `(MyModel*) fznso_model`. 121 + typedef void FznsoModel; 122 + 123 + // The type of a value used as an argument or solution assignment. 124 + // 125 + // This type is opaque to the user. Only pointers of this type are ever used. 126 + // 127 + // In implementation of the FZnSO interface, a pointer is generally cast to 128 + // this type, e.g. `(FznsoValue*) my_value`. A similar cast can be used to cast 129 + // the pointer back to the original type, e.g. `(MyValue*) fznso_value`. 130 + typedef void FznsoValue; 131 + 132 + // Wrapper type for the indexes that represent decision variables in the model. 133 + typedef size_t FznsoDecisionIdx; 134 + 135 + // Wrapper type for the indexes that represent constraints in the model. 136 + typedef size_t FznsoConstraintIdx; 137 + 138 + // A struct containing the function pointers to interact with a 139 + // [`FznsoValue`] 140 + typedef struct FznsoValueMethods { 141 + // Function callback that returns the kind of the value. 142 + enum FznsoValueKind (*kind)(const FznsoValue*); 143 + // Function callback that returns the length of the value. 144 + // 145 + // In case [`FznsoValueMethods::kind`] returns 146 + // [`FznsoValueKind::FznsoValueList`], the length is the number of elements 147 + // in the list, accessible using [`FznsoValueMethods::get_element`]. 148 + // 149 + // In case [`FznsoValueMethods::kind`] returns 150 + // [`FznsoValueKind::FznsoValueSetInt`] or 151 + // [`FznsoValueKind::FznsoValueSetFloat`], the length is the number of 152 + // ranges in the set, accessible using 153 + // [`FznsoValueMethods::get_range_int`] or 154 + // [`FznsoValueMethods::get_range_float`]. 155 + // 156 + // # Panics 157 + // 158 + // This function callback may panic if [`FznsoValueMethods::kind`] does not 159 + // return [`FznsoValueKind::FznsoValueList`], 160 + // [`FznsoValueKind::FznsoValueSetInt`], or 161 + // [`FznsoValueKind::FznsoValueSetFloat`]. 162 + size_t (*len)(const FznsoValue*); 163 + // Function callback that returns the decision variable index contained in 164 + // the value. 165 + // 166 + // # Panics 167 + // 168 + // This function callback may panic if [`FznsoValueMethods::kind`] does not 169 + // return [`FznsoValueKind::FznsoValueDecision`]. 170 + FznsoDecisionIdx (*get_decision)(const FznsoValue*); 171 + // Function callback that returns the constraint index contained in the 172 + // value. 173 + // 174 + // # Panics 175 + // 176 + // This function callback may panic if [`FznsoValueMethods::kind`] does not 177 + // return [`FznsoValueKind::FznsoValueConstraint`]. 178 + FznsoConstraintIdx (*get_constraint)(const FznsoValue*); 179 + // Function callback that returns the integer value contained in the value. 180 + // 181 + // # Panics 182 + // 183 + // This function callback may panic if [`FznsoValueMethods::kind`] does not 184 + // return [`FznsoValueKind::FznsoValueInt`]. 185 + int64_t (*get_int)(const FznsoValue*); 186 + // Function callback that returns the floating point value contained in the 187 + // value. 188 + // 189 + // # Panics 190 + // 191 + // This function callback may panic if [`FznsoValueMethods::kind`] does not 192 + // return [`FznsoValueKind::FznsoValueFloat`]. 193 + double (*get_float)(const FznsoValue*); 194 + // Function callback that returns the string pointer value contained in the 195 + // value. 196 + // 197 + // # Panics 198 + // 199 + // This function callback may panic if [`FznsoValueMethods::kind`] does not 200 + // return [`FznsoValueKind::FznsoValueString`]. 201 + const char *(*get_string)(const FznsoValue*); 202 + // Function callback that returns the Boolean value contained in the value. 203 + // 204 + // # Panics 205 + // 206 + // This function callback may panic if [`FznsoValueMethods::kind`] does not 207 + // return [`FznsoValueKind::FznsoValueBool`]. 208 + bool (*get_bool)(const FznsoValue*); 209 + // Function callback that returns a range from a range list representing 210 + // the integer set contained in the value. 211 + // 212 + // # Panics 213 + // 214 + // This function callback may panic if [`FznsoValueMethods::kind`] does not 215 + // return [`FznsoValueKind::FznsoValueSetInt`]. 216 + int64_t ((*get_range_int)(const FznsoValue*, size_t index))[2]; 217 + // Function callback that returns a range from a range list representing 218 + // the floating point set contained in the value. 219 + // 220 + // # Panics 221 + // 222 + // This function callback may panic if [`FznsoValueMethods::kind`] does not 223 + // return [`FznsoValueKind::FznsoValueSetFloat`]. 224 + double ((*get_range_float)(const FznsoValue*, size_t index))[2]; 225 + // Function callback that returns an element from the list contained in the 226 + // value. 227 + // 228 + // # Panics 229 + // 230 + // This function callback may panic if [`FznsoValueMethods::kind`] does not 231 + // return [`FznsoValueKind::FznsoValueList`]. 232 + struct FznsoValueRef (*get_element)(const FznsoValue*, size_t index); 233 + } FznsoValueMethods; 234 + 235 + // Handle for a value 236 + // 237 + // The caller can use the `get_value` function to retrieve the value of the 238 + // used decision variables. 239 + typedef struct FznsoValueRef { 240 + // The data pointer to be the first argument of `get_value`. 241 + const FznsoValue *data; 242 + // Reference to the structure containing the function callbacks used to 243 + // interact with the value. 244 + const struct FznsoValueMethods *methods; 245 + } FznsoValueRef; 246 + 247 + // A struct containing the function pointers to interact with the 248 + // [`FznsoModel`] 249 + typedef struct FznsoModelMethods { 250 + // Returns the current number of model layers currently contained in the 251 + // model. 252 + // 253 + // Layers provides a way for the modelling user to add and retract 254 + size_t (*layer_len)(const FznsoModel *model); 255 + // Returns the number of layers that have been unchanged since the last 256 + // call to [`fznso_solver_run`]. 257 + // 258 + // Unchanged layers must be consecutive starting from layer 0. 259 + size_t (*layer_unchanged)(const FznsoModel *model); 260 + // Returns the number of permanent layers in the model. 261 + // 262 + // Permanent layers are laid out must be consecutive starting from layer 0. 263 + // Under no circumstances can they be retracted. As such, the solver can 264 + // assume that the number of permanent layers only ever increases. 265 + // 266 + // Permanent layers can, however, still be found to be redundant, allowing 267 + // the solver to remove the decision variables and constraints in these 268 + // layers, if convenient. This is signaled using [`layer_redundant_len`] 269 + // and [`layer_redundant_index`]. 270 + size_t (*layer_permanent)(const FznsoModel *model); 271 + // Returns the number of permanent layers that have been marked as 272 + // redundant. 273 + // 274 + // The solver can remove the decision variables and constraints in these 275 + // layers, if convenient. Once a layer is marked as redundant, it can 276 + // forever be considered redundant. As such, the solver can assume that 277 + // the number of redundant layers only ever increases. 278 + size_t (*layer_redundant_len)(const FznsoModel *model); 279 + // Returns the index of the n-th permanent layer that has been marked as 280 + // redundant. 281 + // 282 + // The `n` argument must be less than the value returned by 283 + // [`layer_redundant_len`]. 284 + size_t (*layer_redundant_index)(const FznsoModel *model, size_t n); 285 + // Retrieve the number of decisions currently contained in the model. 286 + size_t (*decision_len)(const FznsoModel *model); 287 + // Retrieve the decision index of the last decision variable in the layer. 288 + // 289 + // This can be equivalent to `decision_layer_end` of `layer-1` if the layer 290 + // does not add any new decisions. 291 + size_t (*decision_layer_end)(const FznsoModel *model, size_t layer); 292 + // Retrieve the domain of the given decision. 293 + // 294 + // Note that the the value might have [`FznsoValueKind::FznsoValueAbsent`] 295 + // if the decision variable does not have an explicit domain. 296 + struct FznsoValueRef (*decision_domain)(const FznsoModel *model, FznsoDecisionIdx decision); 297 + // Retrieve the name of a decision variable, if it exists. 298 + // 299 + // Note that names are only available for debugging purposes. Decisions are 300 + // identified using their index in the model. If the decision variable does 301 + // not have a name, this function returns a null pointer. 302 + const char *(*decision_name)(const FznsoModel *model, FznsoDecisionIdx decision); 303 + // Check whether the decision variable is defined by a constraint. 304 + bool (*decision_defined)(const FznsoModel *model, FznsoDecisionIdx decision); 305 + // Retrieve the number of annotations of a constraint. 306 + size_t (*decision_annotation_len)(const FznsoModel *model, FznsoDecisionIdx decision); 307 + // Retrieve the value of the constraint's annotation at the given index. 308 + // 309 + // The `index` argument must be less than the value returned by 310 + // [`decision_annotation_len`] for the given decision variable. 311 + const FznsoAnnotation *(*decision_annotation)(const FznsoModel *model, 312 + FznsoDecisionIdx decision, 313 + size_t index); 314 + // Retrieve the number of constraints currently contained in the model. 315 + size_t (*constraint_len)(const FznsoModel *model); 316 + // Retrieve the constraint index of the first new constraint in the layer. 317 + // 318 + // This can be equivalent to `constraint_len` if the layer does not add any 319 + // new constraints. 320 + size_t (*constraint_layer_end)(const FznsoModel *model); 321 + // Retrieve the identifier of a constraint. 322 + // 323 + // The returned pointer can be assumed to have the the same lifetime as the 324 + // model reference and must be valid UTF8. 325 + const char *(*constraint_ident)(const FznsoModel *model, FznsoConstraintIdx constraint); 326 + // Retrieve the number of arguments of a constraint. 327 + size_t (*constraint_argument_len)(const FznsoModel *model, FznsoConstraintIdx constraint); 328 + // Retrieve the value of the constraint's argument at the given index. 329 + // 330 + // The `index` argument must be less than the value returned by 331 + // `constraint_argument_len` for the given constraint. 332 + struct FznsoValueRef (*constraint_argument)(const FznsoModel *model, 333 + FznsoConstraintIdx constraint, 334 + size_t index); 335 + // Check whether the decision variable is functionally defined by a 336 + // constraint. 337 + // 338 + // This function returns a [`FznsoValue`] that is either 339 + // [`FznsoValueKind::FznsoValueDecision`] if it defined a decision variable 340 + // or [`FznsoValueKind::FznsoValueAbsent`] otherwise. 341 + struct FznsoValueRef (*constraint_defines)(const FznsoModel *model, FznsoConstraintIdx constraint); 342 + // Retrieve the number of annotations on a constraint. 343 + size_t (*constraint_annotation_len)(const FznsoModel *model, FznsoConstraintIdx constraint); 344 + // Retrieve the annotation on a constraint at the given index. 345 + // 346 + // The `index` argument must be less than the value returned by 347 + // `constraint_annotation_len` for the given constraint. 348 + const FznsoAnnotation *(*constraint_annotation)(const FznsoModel *model, 349 + FznsoConstraintIdx constraint, 350 + size_t index); 351 + // Request the identifier of the type of objective strategy to be used when 352 + // solving the model. 353 + // 354 + // Note that the function can return a null pointer if the model does not 355 + // have an objective strategy. 356 + const char *(*objective_ident)(const FznsoModel *model); 357 + // Retrieve the argument of the objective strategy. 358 + struct FznsoValueRef (*objective_arg)(const FznsoModel *model); 359 + // Retrieve the number of annotations on an objective 360 + size_t (*objective_annotation_len)(const FznsoModel *model); 361 + // Retrieve the annotation on the objective at the given index. 362 + // 363 + // The `index` argument must be less than the value returned by 364 + // `objective_annotation_len`. 365 + const FznsoAnnotation *(*objective_annotation)(const FznsoModel *model, size_t index); 366 + // Retrieve the identifier of an annotation. 367 + // 368 + // The returned pointer can be assumed to have the the same lifetime as the 369 + // annotation reference and must be valid UTF8. 370 + const char *(*annotation_ident)(const FznsoAnnotation *ann); 371 + // Retrieve the number of arguments of an annotation. 372 + size_t (*annotation_argument_len)(const FznsoAnnotation *ann); 373 + // Retrieve the value of the annotation's argument at the given index. 374 + // 375 + // The `index` argument must be less than the value returned by 376 + // `annotation_argument_len` for the given annotation. 377 + struct FznsoValueRef (*annotation_argument)(const FznsoAnnotation *ann, size_t index); 378 + } FznsoModelMethods; 379 + 380 + // An interface to a model instance used to communicate with the solver. 381 + // 382 + // The solver can use the included function callbacks to interact with the 383 + // model. 384 + typedef struct FznsoModelRef { 385 + // The handle to the data of the model instance. 386 + const FznsoModel *data; 387 + // Reference to the structure containing the function callbacks used to 388 + // interact with the model. 389 + const struct FznsoModelMethods *methods; 390 + } FznsoModelRef; 391 + 392 + // Representation of a type of objective strategies, discerned by its 393 + // identifier and the type of its argument. 394 + typedef struct FznsoObjective { 395 + // The identifier of the objective type. 396 + const char *ident; 397 + // The type of the expected argument for the constraint type. 398 + struct FznsoType arg_type; 399 + } FznsoObjective; 400 + 401 + // A list of [`FznsoObjective`]s. 402 + // 403 + // This type is, for example, used to return from [`fznso_objective_list`]. 404 + typedef struct FznsoObjectiveList { 405 + // The number of elements in the `options` array. 406 + size_t len; 407 + // An array of option definitions. 408 + const struct FznsoObjective *options; 409 + } FznsoObjectiveList; 410 + 411 + // The definition of an option that is available to be set for the solver. 412 + typedef struct FznsoOption { 413 + // The identifier used to set the option or get the current value of the 414 + // option. 415 + const char *ident; 416 + // The type of value that is expected for this option. 417 + struct FznsoValueRef arg_ty; 418 + // The default value for this option. 419 + struct FznsoType arg_def; 420 + } FznsoOption; 421 + 422 + // A list of [`FznsoOption`]s. 423 + // 424 + // This type is, for example, used to return from [`fznso_option_list`]. 425 + typedef struct FznsoOptionList { 426 + // The number of elements in the `options` array. 427 + size_t len; 428 + // An array of option definitions. 429 + const struct FznsoOption *options; 430 + } FznsoOptionList; 431 + 432 + // The handle to a the data of a solution instance. 433 + // 434 + // This type is opaque to the user. Only pointers of this type are ever used. 435 + // 436 + // In implementation of the FZnSO interface, a pointer is generally cast to 437 + // this type, i.e. `(FznsoSolutionData*) my_solution`. A similar cast can be 438 + // used to cast the pointer back to the original type, e.g. `(MySolution*) 439 + // fznso_solution`. 440 + typedef void FznsoSolution; 441 + 442 + // A struct containing the function pointers to interact with a 443 + // [`FznsoSolution`] 444 + typedef struct FznsoSolutionMethods { 445 + // Function callback to retrieve the value assigned to a decision variable 446 + // in the solution. 447 + struct FznsoValueRef (*get_value)(const FznsoSolution *data, size_t decision_index); 448 + // Function callback to retrieve the statistical information made available 449 + // by the solver about the search process so far. 450 + struct FznsoValueRef (*get_statistic)(const FznsoSolution *data, const char *ident); 451 + } FznsoSolutionMethods; 452 + 453 + // Handle for a solution emitted by the solver. 454 + typedef struct FznsoSolutionRef { 455 + // The data pointer to be the first argument of `get_value`. 456 + const FznsoSolution *data; 457 + // Reference to the structure containing the function callbacks used to 458 + // interact with the solution. 459 + const struct FznsoSolutionMethods *methods; 460 + } FznsoSolutionRef; 461 + 462 + // The handle to a solver instance. 463 + // 464 + // This type is opaque to the user. Only pointers of this type are ever used. 465 + // 466 + // In implementation of the FZnSO interface, a pointer is generally cast to 467 + // this type, i.e. `(FznsoSolver*) my_solver`. A similar cast can be used to 468 + // cast the pointer back to the original type, e.g. `(MySolverType*) 469 + // fznso_solver`. 470 + typedef void FznsoSolver; 471 + 472 + // The definition of statistical information that is made available by the 473 + // solver. 474 + typedef struct FznsoStatistic { 475 + // The identifier used to retrieve the statistical information from the 476 + // solver or a solution. 477 + const char *ident; 478 + // The type of value that is expected for this option. 479 + struct FznsoValueRef ty; 480 + // Whether the statistical information is available as part of solutions. 481 + bool solution; 482 + // Whether the statistical information is generally available from the 483 + // solver instance. 484 + bool solver; 485 + } FznsoStatistic; 486 + 487 + // A list of [`FznsoStatistic`]s. 488 + // 489 + // This type is, for example, used to return from [`fznso_statistic_list`]. 490 + typedef struct FznsoStatisticList { 491 + // The number of elements in the `stats` array. 492 + size_t len; 493 + // An array of statistical information definitions. 494 + const struct FznsoStatistic *stats; 495 + } FznsoStatisticList; 496 + 497 + // A list of [`FznsoType`]s. 498 + // 499 + // This type is for example used to return from [`fznso_decision_list`]. 500 + typedef struct FznsoTypeList { 501 + // The number of elements in the `constraints` array. 502 + size_t len; 503 + // An array of constraint types. 504 + const struct FznsoType *types; 505 + } FznsoTypeList; 506 + 507 + #endif /* fznso_types_h */
+18 -18
c/ipdos_solver_template.c c/fznso_solver_template.c
··· 1 - #include "ipdos_types.h" 1 + #include "fznso_types.h" 2 2 3 3 // Returns the list of available constraint that can be added to the solver. 4 - IpdosConstraintList ipdos_constraint_list(void); 4 + FznsoConstraintList fznso_constraint_list(void); 5 5 6 6 // Returns the list of types for which decision variable can be created by the 7 7 // solver. 8 - IpdosTypeList ipdos_decision_list(void); 8 + FznsoTypeList fznso_decision_list(void); 9 9 10 10 // Returns the list of available objective that can be achieved by the solver. 11 - IpdosObjectiveList ipdos_objective_list(void); 11 + FznsoObjectiveList fznso_objective_list(void); 12 12 13 13 // Returns the list of available options that can be set of the solver. 14 - IpdosOptionList ipdos_option_list(void); 14 + FznsoOptionList fznso_option_list(void); 15 15 16 16 // Create a new solver instance 17 - IpdosSolver *ipdos_solver_create(void); 17 + FznsoSolver *fznso_solver_create(void); 18 18 19 19 // Free a solver instance, releasing all resources associated with it. 20 20 // 21 21 // The pointer to the solver instance will be invalid after this function has 22 22 // been called. 23 - void ipdos_solver_free(IpdosSolver *solver); 23 + void fznso_solver_free(FznsoSolver *solver); 24 24 25 25 // Get the current value of an option for the solver. 26 26 // 27 27 // Note that this is only valid to be called with options named by 28 - // `ipdos_option_list`. 29 - IpdosValueRef ipdos_solver_option_get(const IpdosSolver *solver, const char *ident); 28 + // `fznso_option_list`. 29 + FznsoValueRef fznso_solver_option_get(const FznsoSolver *solver, const char *ident); 30 30 31 31 // Set the current value of an option for the solver. 32 32 // 33 33 // Note that this is only valid to be called with options named by 34 - // `ipdos_option_list`, and the value must be of the correct type. 35 - bool ipdos_solver_option_set(IpdosSolver *solver, const char *ident, IpdosValueRef value); 34 + // `fznso_option_list`, and the value must be of the correct type. 35 + bool fznso_solver_option_set(FznsoSolver *solver, const char *ident, FznsoValueRef value); 36 36 37 37 // Read an error message from the solver. 38 38 // 39 39 // This function is expected to be called after solver interactions signal an 40 - // error has occurred. For example, if [`ipdos_solver_run`] returns 41 - // [`IpdosError`] or [`ipdos_solver_push`] returns `false`. 42 - void ipdos_solver_read_error(IpdosSolver *solver, 40 + // error has occurred. For example, if [`fznso_solver_run`] returns 41 + // [`FznsoError`] or [`fznso_solver_push`] returns `false`. 42 + void fznso_solver_read_error(FznsoSolver *solver, 43 43 void *context, 44 44 void (*read_error)(void *context, const char *error)); 45 45 46 46 // Run the solver with the given model 47 - IpdosStatus ipdos_solver_run(IpdosSolver *solver, 48 - IpdosModelRef model, 47 + FznsoStatus fznso_solver_run(FznsoSolver *solver, 48 + FznsoModelRef model, 49 49 void *context, 50 - void (*on_solution)(void *context, IpdosSolutionRef solution)); 50 + void (*on_solution)(void *context, FznsoSolutionRef solution)); 51 51 52 52 // Returns the list of available statistical information that can be requested 53 53 // from the solver and its solutions. 54 - IpdosStatisticList ipdos_statistic_list(void); 54 + FznsoStatisticList fznso_statistic_list(void);
-507
c/ipdos_types.h
··· 1 - #ifndef ipdos_types_h 2 - #define ipdos_types_h 3 - 4 - #include <stdbool.h> 5 - #include <stdint.h> 6 - 7 - // The status returned by `ipdos_solver_run`, indicating whether the solver 8 - // completed its search. 9 - typedef enum IpdosStatus { 10 - // The solver explored the full search space and yielded all relevant 11 - // solutions. 12 - IpdosComplete, 13 - // The solver did not explore the full search space due to a timeout or 14 - // other termination condition. Additional (better) solutions might be 15 - // possible. 16 - IpdosIncomplete, 17 - // An error occurred during the solver's execution. 18 - // 19 - // [`ipdos_solver_read_error`] can be used to retrieve the error message. 20 - IpdosError, 21 - } IpdosStatus; 22 - 23 - // Representation of the base type of a value. 24 - typedef enum IpdosTypeBase { 25 - // Boolean type 26 - IpdosTypeBaseBool, 27 - // Integer numeric type 28 - IpdosTypeBaseInt, 29 - // Floating point numeric type 30 - IpdosTypeBaseFloat, 31 - // Character string type 32 - IpdosTypeBaseString, 33 - } IpdosTypeBase; 34 - 35 - // Enumerated type used to mark the kind of [`IpdosValue`]. This is used to 36 - // determine which "get" method in [`IpdosValueMethods`] is safe to call. 37 - typedef enum IpdosValueKind { 38 - // No value is available. 39 - IpdosValueAbsent, 40 - // The value is available using [`IpdosValueMethods::get_decision`]. 41 - IpdosValueDecision, 42 - // The value is available using [`IpdosValueMethods::get_constraint`]. 43 - IpdosValueConstraint, 44 - // The value is available using [`IpdosValueMethods::get_bool`]. 45 - IpdosValueBool, 46 - // The value is available using [`IpdosValueMethods::get_int`]. 47 - IpdosValueInt, 48 - // The value is available using [`IpdosValueMethods::get_float`]. 49 - IpdosValueFloat, 50 - // The value is available using [`IpdosValueMethods::get_string`]. 51 - IpdosValueString, 52 - // Sets of integers are represented using a range list. The number of 53 - // ranges is available using [`IpdosValueMethods::len`], and the ranges can 54 - // be accessed using [`IpdosValueMethods::get_range_int`]. 55 - IpdosValueSetInt, 56 - // Sets of floats are represented using a range list. The number of 57 - // ranges is available using [`IpdosValueMethods::len`], and the ranges can 58 - // be accessed using [`IpdosValueMethods::get_range_float`]. 59 - IpdosValueSetFloat, 60 - // The length of the list can be accessed using 61 - // [`IpdosValueMethods::len`], and elements in the list can be 62 - // accessed using [`IpdosValueMethods::get_element`] 63 - IpdosValueList, 64 - } IpdosValueKind; 65 - 66 - // The handle to a the data of a solution instance. 67 - // 68 - // This type is opaque to the user. Only pointers of this type are ever used. 69 - // 70 - // In implementation of the IPDOS interface, a pointer is generally cast to 71 - // this type, i.e. `(IpdosSolutionData*) my_solution`. A similar cast can be 72 - // used to cast the pointer back to the original type, e.g. `(MySolution*) 73 - // ipdos_solution`. 74 - typedef void IpdosAnnotation; 75 - 76 - // Representation of a type to signal and check whether an argument takes the 77 - // correct type. 78 - typedef struct IpdosType { 79 - // Whether the type is a list of values. 80 - bool list_of; 81 - // Whether the argument can be or contain decision variables (represented 82 - // as decision indexes). 83 - bool decision; 84 - // Whether expected type is an set of values of the base type. 85 - bool set_of; 86 - // Whether the expected type is optional (and can take the value of 87 - // [`IpdosValueKind::IpdosValueAbsent`]). 88 - bool opt; 89 - // The expected base type of the argument. 90 - enum IpdosTypeBase base; 91 - } IpdosType; 92 - 93 - // Representation of a type of constraint, discerned by its identifier and the 94 - // types of its arguments. 95 - typedef struct IpdosConstraintType { 96 - // The identifier of the constraint type. 97 - const char *ident; 98 - // The number of expected arguments for the constraint type. 99 - size_t arg_len; 100 - // The types of the expected arguments for the constraint type. 101 - const struct IpdosType *arg_types; 102 - } IpdosConstraintType; 103 - 104 - // A list of [`IpdosConstraintType`]s. 105 - // 106 - // This type is for example used to return from [`ipdos_constraint_list`]. 107 - typedef struct IpdosConstraintList { 108 - // The number of elements in the `constraints` array. 109 - size_t len; 110 - // An array of constraint types. 111 - const struct IpdosConstraintType *constraints; 112 - } IpdosConstraintList; 113 - 114 - // The handle of a model instance. 115 - // 116 - // This type is opaque to the user. Only pointers of this type are ever used. 117 - // 118 - // In implementation of the IPDOS interface, a pointer is generally cast to 119 - // this type, i.e. `(IpdosModelData*) my_model`. A similar cast can be used to 120 - // cast the pointer back to the original type, e.g. `(MyModel*) ipdos_model`. 121 - typedef void IpdosModel; 122 - 123 - // The type of a value used as an argument or solution assignment. 124 - // 125 - // This type is opaque to the user. Only pointers of this type are ever used. 126 - // 127 - // In implementation of the IPDOS interface, a pointer is generally cast to 128 - // this type, e.g. `(IpdosValue*) my_value`. A similar cast can be used to cast 129 - // the pointer back to the original type, e.g. `(MyValue*) ipdos_value`. 130 - typedef void IpdosValue; 131 - 132 - // Wrapper type for the indexes that represent decision variables in the model. 133 - typedef size_t IpdosDecisionIdx; 134 - 135 - // Wrapper type for the indexes that represent constraints in the model. 136 - typedef size_t IpdosConstraintIdx; 137 - 138 - // A struct containing the function pointers to interact with a 139 - // [`IpdosValue`] 140 - typedef struct IpdosValueMethods { 141 - // Function callback that returns the kind of the value. 142 - enum IpdosValueKind (*kind)(const IpdosValue*); 143 - // Function callback that returns the length of the value. 144 - // 145 - // In case [`IpdosValueMethods::kind`] returns 146 - // [`IpdosValueKind::IpdosValueList`], the length is the number of elements 147 - // in the list, accessible using [`IpdosValueMethods::get_element`]. 148 - // 149 - // In case [`IpdosValueMethods::kind`] returns 150 - // [`IpdosValueKind::IpdosValueSetInt`] or 151 - // [`IpdosValueKind::IpdosValueSetFloat`], the length is the number of 152 - // ranges in the set, accessible using 153 - // [`IpdosValueMethods::get_range_int`] or 154 - // [`IpdosValueMethods::get_range_float`]. 155 - // 156 - // # Panics 157 - // 158 - // This function callback may panic if [`IpdosValueMethods::kind`] does not 159 - // return [`IpdosValueKind::IpdosValueList`], 160 - // [`IpdosValueKind::IpdosValueSetInt`], or 161 - // [`IpdosValueKind::IpdosValueSetFloat`]. 162 - size_t (*len)(const IpdosValue*); 163 - // Function callback that returns the decision variable index contained in 164 - // the value. 165 - // 166 - // # Panics 167 - // 168 - // This function callback may panic if [`IpdosValueMethods::kind`] does not 169 - // return [`IpdosValueKind::IpdosValueDecision`]. 170 - IpdosDecisionIdx (*get_decision)(const IpdosValue*); 171 - // Function callback that returns the constraint index contained in the 172 - // value. 173 - // 174 - // # Panics 175 - // 176 - // This function callback may panic if [`IpdosValueMethods::kind`] does not 177 - // return [`IpdosValueKind::IpdosValueConstraint`]. 178 - IpdosConstraintIdx (*get_constraint)(const IpdosValue*); 179 - // Function callback that returns the integer value contained in the value. 180 - // 181 - // # Panics 182 - // 183 - // This function callback may panic if [`IpdosValueMethods::kind`] does not 184 - // return [`IpdosValueKind::IpdosValueInt`]. 185 - int64_t (*get_int)(const IpdosValue*); 186 - // Function callback that returns the floating point value contained in the 187 - // value. 188 - // 189 - // # Panics 190 - // 191 - // This function callback may panic if [`IpdosValueMethods::kind`] does not 192 - // return [`IpdosValueKind::IpdosValueFloat`]. 193 - double (*get_float)(const IpdosValue*); 194 - // Function callback that returns the string pointer value contained in the 195 - // value. 196 - // 197 - // # Panics 198 - // 199 - // This function callback may panic if [`IpdosValueMethods::kind`] does not 200 - // return [`IpdosValueKind::IpdosValueString`]. 201 - const char *(*get_string)(const IpdosValue*); 202 - // Function callback that returns the Boolean value contained in the value. 203 - // 204 - // # Panics 205 - // 206 - // This function callback may panic if [`IpdosValueMethods::kind`] does not 207 - // return [`IpdosValueKind::IpdosValueBool`]. 208 - bool (*get_bool)(const IpdosValue*); 209 - // Function callback that returns a range from a range list representing 210 - // the integer set contained in the value. 211 - // 212 - // # Panics 213 - // 214 - // This function callback may panic if [`IpdosValueMethods::kind`] does not 215 - // return [`IpdosValueKind::IpdosValueSetInt`]. 216 - int64_t ((*get_range_int)(const IpdosValue*, size_t index))[2]; 217 - // Function callback that returns a range from a range list representing 218 - // the floating point set contained in the value. 219 - // 220 - // # Panics 221 - // 222 - // This function callback may panic if [`IpdosValueMethods::kind`] does not 223 - // return [`IpdosValueKind::IpdosValueSetFloat`]. 224 - double ((*get_range_float)(const IpdosValue*, size_t index))[2]; 225 - // Function callback that returns an element from the list contained in the 226 - // value. 227 - // 228 - // # Panics 229 - // 230 - // This function callback may panic if [`IpdosValueMethods::kind`] does not 231 - // return [`IpdosValueKind::IpdosValueList`]. 232 - struct IpdosValueRef (*get_element)(const IpdosValue*, size_t index); 233 - } IpdosValueMethods; 234 - 235 - // Handle for a value 236 - // 237 - // The caller can use the `get_value` function to retrieve the value of the 238 - // used decision variables. 239 - typedef struct IpdosValueRef { 240 - // The data pointer to be the first argument of `get_value`. 241 - const IpdosValue *data; 242 - // Reference to the structure containing the function callbacks used to 243 - // interact with the value. 244 - const struct IpdosValueMethods *methods; 245 - } IpdosValueRef; 246 - 247 - // A struct containing the function pointers to interact with the 248 - // [`IpdosModel`] 249 - typedef struct IpdosModelMethods { 250 - // Returns the current number of model layers currently contained in the 251 - // model. 252 - // 253 - // Layers provides a way for the modelling user to add and retract 254 - size_t (*layer_len)(const IpdosModel *model); 255 - // Returns the number of layers that have been unchanged since the last 256 - // call to [`ipdos_solver_run`]. 257 - // 258 - // Unchanged layers must be consecutive starting from layer 0. 259 - size_t (*layer_unchanged)(const IpdosModel *model); 260 - // Returns the number of permanent layers in the model. 261 - // 262 - // Permanent layers are laid out must be consecutive starting from layer 0. 263 - // Under no circumstances can they be retracted. As such, the solver can 264 - // assume that the number of permanent layers only ever increases. 265 - // 266 - // Permanent layers can, however, still be found to be redundant, allowing 267 - // the solver to remove the decision variables and constraints in these 268 - // layers, if convenient. This is signaled using [`layer_redundant_len`] 269 - // and [`layer_redundant_index`]. 270 - size_t (*layer_permanent)(const IpdosModel *model); 271 - // Returns the number of permanent layers that have been marked as 272 - // redundant. 273 - // 274 - // The solver can remove the decision variables and constraints in these 275 - // layers, if convenient. Once a layer is marked as redundant, it can 276 - // forever be considered redundant. As such, the solver can assume that 277 - // the number of redundant layers only ever increases. 278 - size_t (*layer_redundant_len)(const IpdosModel *model); 279 - // Returns the index of the n-th permanent layer that has been marked as 280 - // redundant. 281 - // 282 - // The `n` argument must be less than the value returned by 283 - // [`layer_redundant_len`]. 284 - size_t (*layer_redundant_index)(const IpdosModel *model, size_t n); 285 - // Retrieve the number of decisions currently contained in the model. 286 - size_t (*decision_len)(const IpdosModel *model); 287 - // Retrieve the decision index of the last decision variable in the layer. 288 - // 289 - // This can be equivalent to `decision_layer_end` of `layer-1` if the layer 290 - // does not add any new decisions. 291 - size_t (*decision_layer_end)(const IpdosModel *model, size_t layer); 292 - // Retrieve the domain of the given decision. 293 - // 294 - // Note that the the value might have [`IpdosValueKind::IpdosValueAbsent`] 295 - // if the decision variable does not have an explicit domain. 296 - struct IpdosValueRef (*decision_domain)(const IpdosModel *model, IpdosDecisionIdx decision); 297 - // Retrieve the name of a decision variable, if it exists. 298 - // 299 - // Note that names are only available for debugging purposes. Decisions are 300 - // identified using their index in the model. If the decision variable does 301 - // not have a name, this function returns a null pointer. 302 - const char *(*decision_name)(const IpdosModel *model, IpdosDecisionIdx decision); 303 - // Check whether the decision variable is defined by a constraint. 304 - bool (*decision_defined)(const IpdosModel *model, IpdosDecisionIdx decision); 305 - // Retrieve the number of annotations of a constraint. 306 - size_t (*decision_annotation_len)(const IpdosModel *model, IpdosDecisionIdx decision); 307 - // Retrieve the value of the constraint's annotation at the given index. 308 - // 309 - // The `index` argument must be less than the value returned by 310 - // [`decision_annotation_len`] for the given decision variable. 311 - const IpdosAnnotation *(*decision_annotation)(const IpdosModel *model, 312 - IpdosDecisionIdx decision, 313 - size_t index); 314 - // Retrieve the number of constraints currently contained in the model. 315 - size_t (*constraint_len)(const IpdosModel *model); 316 - // Retrieve the constraint index of the first new constraint in the layer. 317 - // 318 - // This can be equivalent to `constraint_len` if the layer does not add any 319 - // new constraints. 320 - size_t (*constraint_layer_end)(const IpdosModel *model); 321 - // Retrieve the identifier of a constraint. 322 - // 323 - // The returned pointer can be assumed to have the the same lifetime as the 324 - // model reference and must be valid UTF8. 325 - const char *(*constraint_ident)(const IpdosModel *model, IpdosConstraintIdx constraint); 326 - // Retrieve the number of arguments of a constraint. 327 - size_t (*constraint_argument_len)(const IpdosModel *model, IpdosConstraintIdx constraint); 328 - // Retrieve the value of the constraint's argument at the given index. 329 - // 330 - // The `index` argument must be less than the value returned by 331 - // `constraint_argument_len` for the given constraint. 332 - struct IpdosValueRef (*constraint_argument)(const IpdosModel *model, 333 - IpdosConstraintIdx constraint, 334 - size_t index); 335 - // Check whether the decision variable is functionally defined by a 336 - // constraint. 337 - // 338 - // This function returns a [`IpdosValue`] that is either 339 - // [`IpdosValueKind::IpdosValueDecision`] if it defined a decision variable 340 - // or [`IpdosValueKind::IpdosValueAbsent`] otherwise. 341 - struct IpdosValueRef (*constraint_defines)(const IpdosModel *model, IpdosConstraintIdx constraint); 342 - // Retrieve the number of annotations on a constraint. 343 - size_t (*constraint_annotation_len)(const IpdosModel *model, IpdosConstraintIdx constraint); 344 - // Retrieve the annotation on a constraint at the given index. 345 - // 346 - // The `index` argument must be less than the value returned by 347 - // `constraint_annotation_len` for the given constraint. 348 - const IpdosAnnotation *(*constraint_annotation)(const IpdosModel *model, 349 - IpdosConstraintIdx constraint, 350 - size_t index); 351 - // Request the identifier of the type of objective strategy to be used when 352 - // solving the model. 353 - // 354 - // Note that the function can return a null pointer if the model does not 355 - // have an objective strategy. 356 - const char *(*objective_ident)(const IpdosModel *model); 357 - // Retrieve the argument of the objective strategy. 358 - struct IpdosValueRef (*objective_arg)(const IpdosModel *model); 359 - // Retrieve the number of annotations on an objective 360 - size_t (*objective_annotation_len)(const IpdosModel *model); 361 - // Retrieve the annotation on the objective at the given index. 362 - // 363 - // The `index` argument must be less than the value returned by 364 - // `objective_annotation_len`. 365 - const IpdosAnnotation *(*objective_annotation)(const IpdosModel *model, size_t index); 366 - // Retrieve the identifier of an annotation. 367 - // 368 - // The returned pointer can be assumed to have the the same lifetime as the 369 - // annotation reference and must be valid UTF8. 370 - const char *(*annotation_ident)(const IpdosAnnotation *ann); 371 - // Retrieve the number of arguments of an annotation. 372 - size_t (*annotation_argument_len)(const IpdosAnnotation *ann); 373 - // Retrieve the value of the annotation's argument at the given index. 374 - // 375 - // The `index` argument must be less than the value returned by 376 - // `annotation_argument_len` for the given annotation. 377 - struct IpdosValueRef (*annotation_argument)(const IpdosAnnotation *ann, size_t index); 378 - } IpdosModelMethods; 379 - 380 - // An interface to a model instance used to communicate with the solver. 381 - // 382 - // The solver can use the included function callbacks to interact with the 383 - // model. 384 - typedef struct IpdosModelRef { 385 - // The handle to the data of the model instance. 386 - const IpdosModel *data; 387 - // Reference to the structure containing the function callbacks used to 388 - // interact with the model. 389 - const struct IpdosModelMethods *methods; 390 - } IpdosModelRef; 391 - 392 - // Representation of a type of objective strategies, discerned by its 393 - // identifier and the type of its argument. 394 - typedef struct IpdosObjective { 395 - // The identifier of the objective type. 396 - const char *ident; 397 - // The type of the expected argument for the constraint type. 398 - struct IpdosType arg_type; 399 - } IpdosObjective; 400 - 401 - // A list of [`IpdosObjective`]s. 402 - // 403 - // This type is, for example, used to return from [`ipdos_objective_list`]. 404 - typedef struct IpdosObjectiveList { 405 - // The number of elements in the `options` array. 406 - size_t len; 407 - // An array of option definitions. 408 - const struct IpdosObjective *options; 409 - } IpdosObjectiveList; 410 - 411 - // The definition of an option that is available to be set for the solver. 412 - typedef struct IpdosOption { 413 - // The identifier used to set the option or get the current value of the 414 - // option. 415 - const char *ident; 416 - // The type of value that is expected for this option. 417 - struct IpdosValueRef arg_ty; 418 - // The default value for this option. 419 - struct IpdosType arg_def; 420 - } IpdosOption; 421 - 422 - // A list of [`IpdosOption`]s. 423 - // 424 - // This type is, for example, used to return from [`ipdos_option_list`]. 425 - typedef struct IpdosOptionList { 426 - // The number of elements in the `options` array. 427 - size_t len; 428 - // An array of option definitions. 429 - const struct IpdosOption *options; 430 - } IpdosOptionList; 431 - 432 - // The handle to a the data of a solution instance. 433 - // 434 - // This type is opaque to the user. Only pointers of this type are ever used. 435 - // 436 - // In implementation of the IPDOS interface, a pointer is generally cast to 437 - // this type, i.e. `(IpdosSolutionData*) my_solution`. A similar cast can be 438 - // used to cast the pointer back to the original type, e.g. `(MySolution*) 439 - // ipdos_solution`. 440 - typedef void IpdosSolution; 441 - 442 - // A struct containing the function pointers to interact with a 443 - // [`IpdosSolution`] 444 - typedef struct IpdosSolutionMethods { 445 - // Function callback to retrieve the value assigned to a decision variable 446 - // in the solution. 447 - struct IpdosValueRef (*get_value)(const IpdosSolution *data, size_t decision_index); 448 - // Function callback to retrieve the statistical information made available 449 - // by the solver about the search process so far. 450 - struct IpdosValueRef (*get_statistic)(const IpdosSolution *data, const char *ident); 451 - } IpdosSolutionMethods; 452 - 453 - // Handle for a solution emitted by the solver. 454 - typedef struct IpdosSolutionRef { 455 - // The data pointer to be the first argument of `get_value`. 456 - const IpdosSolution *data; 457 - // Reference to the structure containing the function callbacks used to 458 - // interact with the solution. 459 - const struct IpdosSolutionMethods *methods; 460 - } IpdosSolutionRef; 461 - 462 - // The handle to a solver instance. 463 - // 464 - // This type is opaque to the user. Only pointers of this type are ever used. 465 - // 466 - // In implementation of the IPDOS interface, a pointer is generally cast to 467 - // this type, i.e. `(IpdosSolver*) my_solver`. A similar cast can be used to 468 - // cast the pointer back to the original type, e.g. `(MySolverType*) 469 - // ipdos_solver`. 470 - typedef void IpdosSolver; 471 - 472 - // The definition of statistical information that is made available by the 473 - // solver. 474 - typedef struct IpdosStatistic { 475 - // The identifier used to retrieve the statistical information from the 476 - // solver or a solution. 477 - const char *ident; 478 - // The type of value that is expected for this option. 479 - struct IpdosValueRef ty; 480 - // Whether the statistical information is available as part of solutions. 481 - bool solution; 482 - // Whether the statistical information is generally available from the 483 - // solver instance. 484 - bool solver; 485 - } IpdosStatistic; 486 - 487 - // A list of [`IpdosStatistic`]s. 488 - // 489 - // This type is, for example, used to return from [`ipdos_statistic_list`]. 490 - typedef struct IpdosStatisticList { 491 - // The number of elements in the `stats` array. 492 - size_t len; 493 - // An array of statistical information definitions. 494 - const struct IpdosStatistic *stats; 495 - } IpdosStatisticList; 496 - 497 - // A list of [`IpdosType`]s. 498 - // 499 - // This type is for example used to return from [`ipdos_decision_list`]. 500 - typedef struct IpdosTypeList { 501 - // The number of elements in the `constraints` array. 502 - size_t len; 503 - // An array of constraint types. 504 - const struct IpdosType *types; 505 - } IpdosTypeList; 506 - 507 - #endif /* ipdos_types_h */
+25 -25
cbindgen_template.toml
··· 3 3 # Wrapping header contents 4 4 documentation_style = "c99" 5 5 no_includes = true 6 - includes = ["ipdos_types.h"] 6 + includes = ["fznso_types.h"] 7 7 cpp_compat = false 8 8 usize_is_size_t = true 9 9 ··· 12 12 13 13 [export] 14 14 exclude = [ 15 - "IpdosAnnotation", 16 - "IpdosConstraintList", 17 - "IpdosConstraintType", 18 - "IpdosModel", 19 - "IpdosModelMethods", 20 - "IpdosModelRef", 21 - "IpdosObjective", 22 - "IpdosObjectiveList", 23 - "IpdosOption", 24 - "IpdosOptionList", 25 - "IpdosSolution", 26 - "IpdosSolutionMethods", 27 - "IpdosSolutionRef", 28 - "IpdosSolver", 29 - "IpdosStatistic", 30 - "IpdosStatisticList", 31 - "IpdosStatus", 32 - "IpdosType", 33 - "IpdosTypeBase", 34 - "IpdosTypeList", 35 - "IpdosValue", 36 - "IpdosValueKind", 37 - "IpdosValueMethods", 38 - "IpdosValueRef", 15 + "FznsoAnnotation", 16 + "FznsoConstraintList", 17 + "FznsoConstraintType", 18 + "FznsoModel", 19 + "FznsoModelMethods", 20 + "FznsoModelRef", 21 + "FznsoObjective", 22 + "FznsoObjectiveList", 23 + "FznsoOption", 24 + "FznsoOptionList", 25 + "FznsoSolution", 26 + "FznsoSolutionMethods", 27 + "FznsoSolutionRef", 28 + "FznsoSolver", 29 + "FznsoStatistic", 30 + "FznsoStatisticList", 31 + "FznsoStatus", 32 + "FznsoType", 33 + "FznsoTypeBase", 34 + "FznsoTypeList", 35 + "FznsoValue", 36 + "FznsoValueKind", 37 + "FznsoValueMethods", 38 + "FznsoValueRef", 39 39 ]
+25 -25
cbindgen_types.toml
··· 1 1 language = "C" 2 2 3 3 # Wrapping header contents 4 - include_guard = "ipdos_types_h" 4 + include_guard = "fznso_types_h" 5 5 documentation_style = "c99" 6 6 sys_includes = ["stdbool.h", "stdint.h"] 7 7 no_includes = true ··· 9 9 10 10 [export] 11 11 include = [ 12 - "IpdosAnnotation", 13 - "IpdosConstraintList", 14 - "IpdosConstraintType", 15 - "IpdosModel", 16 - "IpdosModelMethods", 17 - "IpdosModelRef", 18 - "IpdosObjective", 19 - "IpdosObjectiveList", 20 - "IpdosOption", 21 - "IpdosOptionList", 22 - "IpdosSolution", 23 - "IpdosSolutionMethods", 24 - "IpdosSolutionRef", 25 - "IpdosSolver", 26 - "IpdosStatistic", 27 - "IpdosStatisticList", 28 - "IpdosStatus", 29 - "IpdosType", 30 - "IpdosTypeBase", 31 - "IpdosTypeList", 32 - "IpdosValue", 33 - "IpdosValueKind", 34 - "IpdosValueMethods", 35 - "IpdosValueRef", 12 + "FznsoAnnotation", 13 + "FznsoConstraintList", 14 + "FznsoConstraintType", 15 + "FznsoModel", 16 + "FznsoModelMethods", 17 + "FznsoModelRef", 18 + "FznsoObjective", 19 + "FznsoObjectiveList", 20 + "FznsoOption", 21 + "FznsoOptionList", 22 + "FznsoSolution", 23 + "FznsoSolutionMethods", 24 + "FznsoSolutionRef", 25 + "FznsoSolver", 26 + "FznsoStatistic", 27 + "FznsoStatisticList", 28 + "FznsoStatus", 29 + "FznsoType", 30 + "FznsoTypeBase", 31 + "FznsoTypeList", 32 + "FznsoValue", 33 + "FznsoValueKind", 34 + "FznsoValueMethods", 35 + "FznsoValueRef", 36 36 ]
+1 -1
codebook.toml
··· 1 - words = ["ipdos"] 1 + words = ["fznso"]
+465
rust/fznso-types/src/rust_interaction.rs
··· 1 + //! Implementations and extensions that helps interacting with the ABI FZnSO 2 + //! types in Rust. 3 + 4 + use std::{ffi, mem}; 5 + 6 + use crate::{ 7 + FznsoConstraintIdx, FznsoDecisionIdx, FznsoValue, FznsoValueKind, FznsoValueMethods, 8 + FznsoValueRef, 9 + }; 10 + 11 + /// Macro used to create [`FznsoValueRef`] from vector and option types. 12 + macro_rules! fznso_value_impls { 13 + (vec $t:ty) => { 14 + impl<'a> From<&'a Vec<$t>> for FznsoValueRef<'a> { 15 + fn from(value: &'a Vec<$t>) -> Self { 16 + extern "C" fn kind(_: &FznsoValue) -> FznsoValueKind { 17 + FznsoValueKind::FznsoValueList 18 + } 19 + extern "C" fn len(val: &FznsoValue) -> usize { 20 + // SAFETY: The value is a &'a Vec<$t>, but was transmuted to a FznsoValue to fit [`FznsoValueRef`]. 21 + let val: &Vec<$t> = unsafe { mem::transmute(val) }; 22 + val.len() 23 + } 24 + extern "C" fn get_element<'a>(val: &'a FznsoValue, idx: usize) -> FznsoValueRef<'a> { 25 + // SAFETY: The value is a &'a Vec<$t>, but was transmuted to a FznsoValue to fit [`FznsoValueRef`]. 26 + let val: &Vec<$t> = unsafe { mem::transmute(val) }; 27 + FznsoValueRef::from(&val[idx]) 28 + } 29 + const FZNSO_LIST_VALUE_METHODS: &'static FznsoValueMethods = &FznsoValueMethods { 30 + kind, 31 + len, 32 + get_element, 33 + ..*FznsoValueRef::FZNSO_DEFAULT_VALUE_METHODS 34 + }; 35 + 36 + // SAFETY: The value is a &'a Vec<$t>, and will never be used without transmuting back. 37 + let data: &FznsoValue = unsafe { mem::transmute(value) }; 38 + Self { 39 + data, 40 + methods: FZNSO_LIST_VALUE_METHODS, 41 + } 42 + } 43 + } 44 + 45 + impl TryFrom<&FznsoValueRef<'_>> for Vec<$t> { 46 + type Error = (); 47 + 48 + fn try_from(value: &FznsoValueRef<'_>) -> Result<Self, Self::Error> { 49 + if value.kind() != FznsoValueKind::FznsoValueList { 50 + return Err(()); 51 + } 52 + let len = value.len(); 53 + let mut result = Vec::with_capacity(len); 54 + for i in 0..len { 55 + result.push((&value.get_element(i)).try_into()?); 56 + } 57 + Ok(result) 58 + } 59 + } 60 + }; 61 + 62 + (opt $t:ty) => { 63 + impl From<&Option<$t>> for FznsoValueRef<'_> { 64 + fn from(value: &Option<$t>) -> Self { 65 + match value { 66 + Some(t) => FznsoValueRef::from(t), 67 + None => FznsoValueRef::from(&()), 68 + } 69 + } 70 + } 71 + 72 + impl TryFrom<&FznsoValueRef<'_>> for Option<$t> { 73 + type Error = (); 74 + 75 + fn try_from(value: &FznsoValueRef<'_>) -> Result<Self, Self::Error> { 76 + if value.kind() == FznsoValueKind::FznsoValueAbsent { 77 + Ok(None) 78 + } else { 79 + let val = value.try_into()?; 80 + Ok(Some(val)) 81 + } 82 + } 83 + } 84 + }; 85 + ($( $t:ty ),+) => { 86 + $( 87 + fznso_value_impls!{vec $t} 88 + fznso_value_impls!{opt $t} 89 + fznso_value_impls!{vec Option<$t>} 90 + )+ 91 + }; 92 + } 93 + 94 + impl FznsoValueRef<'_> { 95 + /// Default [`FznsoValueMethods`] implementation, which can be used for 96 + /// absent values or as a base for other value types. 97 + const FZNSO_DEFAULT_VALUE_METHODS: &'static FznsoValueMethods = &FznsoValueMethods { 98 + kind: Self::absent_kind, 99 + len: Self::no_call, 100 + get_decision: Self::no_call, 101 + get_constraint: Self::no_call, 102 + get_int: Self::no_call, 103 + get_float: Self::no_call, 104 + get_string: Self::no_call, 105 + get_bool: Self::no_call, 106 + get_range_int: Self::no_call_idx, 107 + get_range_float: Self::no_call_idx, 108 + get_element: Self::no_call_idx, 109 + }; 110 + 111 + /// Function that always returns [`FznsoValueKind::FznsoValueAbsent`]. 112 + extern "C" fn absent_kind(_: &FznsoValue) -> FznsoValueKind { 113 + FznsoValueKind::FznsoValueAbsent 114 + } 115 + /// Fallback implementation for different value methods that always panics. 116 + extern "C" fn no_call<T>(_: &FznsoValue) -> T { 117 + panic!("This value implementation does not provide this callback"); 118 + } 119 + /// Fallback implementation for value methods that take a `usize` argument 120 + /// that always panics. 121 + extern "C" fn no_call_idx<T>(v: &FznsoValue, _: usize) -> T { 122 + Self::no_call(v) 123 + } 124 + 125 + /// Rust call to [`FznsoValueMethods::kind`] with the 126 + /// [`FznsoValueRef::data`] attribute. 127 + pub fn kind(&self) -> FznsoValueKind { 128 + (self.methods.kind)(self.data) 129 + } 130 + 131 + /// Rust call to [`FznsoValueMethods::len`] with the [`FznsoValueRef::data`] 132 + /// attribute. 133 + pub fn len(&self) -> usize { 134 + (self.methods.len)(self.data) 135 + } 136 + 137 + /// Wrapper for a call to [`FznsoValueMethods::len`] with the 138 + /// [`FznsoValueRef::data`] attribute, returning `true` if the `len` is 139 + /// zero. 140 + pub fn is_empty(&self) -> bool { 141 + self.len() == 0 142 + } 143 + 144 + /// Rust call to [`FznsoValueMethods::get_decision`] with the 145 + /// [`FznsoValueRef::data`] attribute. 146 + pub fn get_decision(&self) -> FznsoDecisionIdx { 147 + (self.methods.get_decision)(self.data) 148 + } 149 + 150 + /// Rust call to [`FznsoValueMethods::get_constraint`] with the 151 + /// [`FznsoValueRef::data`] attribute. 152 + pub fn get_constraint(&self) -> FznsoConstraintIdx { 153 + (self.methods.get_constraint)(self.data) 154 + } 155 + 156 + /// Rust call to [`FznsoValueMethods::get_int`] with the 157 + /// [`FznsoValueRef::data`] attribute. 158 + pub fn get_int(&self) -> i64 { 159 + (self.methods.get_int)(self.data) 160 + } 161 + 162 + /// Rust call to [`FznsoValueMethods::get_float`] with the 163 + /// [`FznsoValueRef::data`] attribute. 164 + pub fn get_float(&self) -> f64 { 165 + (self.methods.get_float)(self.data) 166 + } 167 + 168 + /// Rust call to [`FznsoValueMethods::get_string`] with the 169 + /// [`FznsoValueRef::data`] attribute. 170 + pub fn get_string(&self) -> &'_ ffi::CStr { 171 + let s = (self.methods.get_string)(self.data); 172 + // SAFETY: The string is valid UTF-8 and null-terminated. 173 + unsafe { ffi::CStr::from_ptr(s) } 174 + } 175 + 176 + /// Rust call to [`FznsoValueMethods::get_bool`] with the 177 + /// [`FznsoValueRef::data`] attribute. 178 + pub fn get_bool(&self) -> bool { 179 + (self.methods.get_bool)(self.data) 180 + } 181 + 182 + /// Rust call to [`FznsoValueMethods::get_range_int`] with the 183 + /// [`FznsoValueRef::data`] attribute. 184 + pub fn get_range_int(&self, idx: usize) -> (i64, i64) { 185 + let [min, max] = (self.methods.get_range_int)(self.data, idx); 186 + (min, max) 187 + } 188 + 189 + /// Rust call to [`FznsoValueMethods::get_range_float`] with the 190 + /// [`FznsoValueRef::data`] attribute. 191 + pub fn get_range_float(&self, idx: usize) -> (f64, f64) { 192 + let [min, max] = (self.methods.get_range_float)(self.data, idx); 193 + (min, max) 194 + } 195 + 196 + /// Rust call to [`FznsoValueMethods::get_element`] with the 197 + /// [`FznsoValueRef::data`] attribute. 198 + pub fn get_element(&self, idx: usize) -> FznsoValueRef<'_> { 199 + (self.methods.get_element)(self.data, idx) 200 + } 201 + } 202 + 203 + impl From<&()> for FznsoValueRef<'_> { 204 + fn from(value: &()) -> Self { 205 + // SAFETY: The value is a &'a (), but was transmuted to a &'a FznsoValue 206 + // to fit [`FznsoValueRef`]. 207 + let data: &FznsoValue = unsafe { mem::transmute(value) }; 208 + Self { 209 + data, 210 + methods: Self::FZNSO_DEFAULT_VALUE_METHODS, 211 + } 212 + } 213 + } 214 + 215 + impl From<&bool> for FznsoValueRef<'_> { 216 + fn from(value: &bool) -> Self { 217 + extern "C" fn kind(_: &FznsoValue) -> FznsoValueKind { 218 + FznsoValueKind::FznsoValueBool 219 + } 220 + extern "C" fn get_bool(val: &FznsoValue) -> bool { 221 + // SAFETY: The value is a &'a bool, but was transmuted to a &'a FznsoValue 222 + // to fit [`FznsoValueRef`]. 223 + let val: &bool = unsafe { mem::transmute(val) }; 224 + *val 225 + } 226 + const FZNSO_BOOL_VALUE_METHODS: &FznsoValueMethods = &FznsoValueMethods { 227 + kind, 228 + get_bool, 229 + ..*FznsoValueRef::FZNSO_DEFAULT_VALUE_METHODS 230 + }; 231 + 232 + // SAFETY: The value is a &'a bool, but was transmuted to a &'a FznsoValue 233 + // to fit [`FznsoValueRef`]. 234 + let data: &FznsoValue = unsafe { mem::transmute(value) }; 235 + Self { 236 + data, 237 + methods: FZNSO_BOOL_VALUE_METHODS, 238 + } 239 + } 240 + } 241 + 242 + impl From<&f64> for FznsoValueRef<'_> { 243 + fn from(value: &f64) -> Self { 244 + extern "C" fn kind(_: &FznsoValue) -> FznsoValueKind { 245 + FznsoValueKind::FznsoValueInt 246 + } 247 + extern "C" fn get_float(val: &FznsoValue) -> f64 { 248 + // SAFETY: The value is a &'a f64, but was transmuted to a &'a FznsoValue 249 + // to fit [`FznsoValueRef`]. 250 + let val: &f64 = unsafe { mem::transmute(val) }; 251 + *val 252 + } 253 + const FZNSO_F64_VALUE_METHODS: &FznsoValueMethods = &FznsoValueMethods { 254 + kind, 255 + get_float, 256 + ..*FznsoValueRef::FZNSO_DEFAULT_VALUE_METHODS 257 + }; 258 + 259 + // SAFETY: The value is a &'a f64, but was transmuted to a &'a FznsoValue to 260 + // fit [`FznsoValueRef`]. 261 + let data: &FznsoValue = unsafe { mem::transmute(value) }; 262 + Self { 263 + data, 264 + methods: FZNSO_F64_VALUE_METHODS, 265 + } 266 + } 267 + } 268 + 269 + impl From<&i64> for FznsoValueRef<'_> { 270 + fn from(value: &i64) -> Self { 271 + extern "C" fn kind(_: &FznsoValue) -> FznsoValueKind { 272 + FznsoValueKind::FznsoValueInt 273 + } 274 + extern "C" fn get_int(val: &FznsoValue) -> i64 { 275 + // SAFETY: The value is a &'a i64, but was transmuted to a &'a FznsoValue 276 + // to fit [`FznsoValueRef`]. 277 + let val: &i64 = unsafe { mem::transmute(val) }; 278 + *val 279 + } 280 + const FZNSO_I64_VALUE_METHODS: &FznsoValueMethods = &FznsoValueMethods { 281 + kind, 282 + get_int, 283 + ..*FznsoValueRef::FZNSO_DEFAULT_VALUE_METHODS 284 + }; 285 + 286 + // SAFETY: The value is a &'a i64, but was transmuted to a &'a FznsoValue to 287 + // fit [`FznsoValueRef`]. 288 + let data: &FznsoValue = unsafe { mem::transmute(value) }; 289 + Self { 290 + data, 291 + methods: FZNSO_I64_VALUE_METHODS, 292 + } 293 + } 294 + } 295 + 296 + impl From<&ffi::CStr> for FznsoValueRef<'_> { 297 + fn from(value: &ffi::CStr) -> Self { 298 + extern "C" fn kind(_: &FznsoValue) -> FznsoValueKind { 299 + FznsoValueKind::FznsoValueString 300 + } 301 + extern "C" fn get_string(val: &FznsoValue) -> *const ffi::c_char { 302 + let val: *const _ = val; 303 + val as *const ffi::c_char 304 + } 305 + const FZNSO_STR_VALUE_METHODS: &FznsoValueMethods = &FznsoValueMethods { 306 + kind, 307 + get_string, 308 + ..*FznsoValueRef::FZNSO_DEFAULT_VALUE_METHODS 309 + }; 310 + 311 + // SAFETY: The value is a &'a ffi::CStr, but was transmuted to a &'a 312 + // FznsoValue to fit [`FznsoValueRef`]. 313 + let data: &FznsoValue = unsafe { &*(value.as_ptr() as *const FznsoValue) }; 314 + Self { 315 + data, 316 + methods: FZNSO_STR_VALUE_METHODS, 317 + } 318 + } 319 + } 320 + 321 + impl From<&ffi::CString> for FznsoValueRef<'_> { 322 + fn from(value: &ffi::CString) -> Self { 323 + value.as_c_str().into() 324 + } 325 + } 326 + 327 + impl From<&FznsoConstraintIdx> for FznsoValueRef<'_> { 328 + fn from(value: &FznsoConstraintIdx) -> Self { 329 + extern "C" fn kind(_: &FznsoValue) -> FznsoValueKind { 330 + FznsoValueKind::FznsoValueDecision 331 + } 332 + extern "C" fn get_constraint(val: &FznsoValue) -> FznsoConstraintIdx { 333 + // SAFETY: The value is a &'a FznsoConstraintIdx, but was transmuted to a 334 + // &'a FznsoValue to fit [`FznsoValueRef`]. 335 + let val: &FznsoConstraintIdx = unsafe { mem::transmute(val) }; 336 + *val 337 + } 338 + const FZNSO_CONSTRAINT_VALUE_METHODS: &FznsoValueMethods = &FznsoValueMethods { 339 + kind, 340 + get_constraint, 341 + ..*FznsoValueRef::FZNSO_DEFAULT_VALUE_METHODS 342 + }; 343 + 344 + // SAFETY: The value is a &'a FznsoConstraintIdx, and will never be used 345 + // without transmuting back. 346 + let data: &FznsoValue = unsafe { mem::transmute(value) }; 347 + Self { 348 + data, 349 + methods: FZNSO_CONSTRAINT_VALUE_METHODS, 350 + } 351 + } 352 + } 353 + 354 + impl From<&FznsoDecisionIdx> for FznsoValueRef<'_> { 355 + fn from(value: &FznsoDecisionIdx) -> Self { 356 + extern "C" fn kind(_: &FznsoValue) -> FznsoValueKind { 357 + FznsoValueKind::FznsoValueDecision 358 + } 359 + extern "C" fn get_decision(val: &FznsoValue) -> FznsoDecisionIdx { 360 + // SAFETY: The value is a &'a FznsoDecisionIdx, but was transmuted to a 361 + // &'a FznsoValue to fit [`FznsoValueRef`]. 362 + let val: &FznsoDecisionIdx = unsafe { mem::transmute(val) }; 363 + *val 364 + } 365 + const FZNSO_DECISION_VALUE_METHODS: &FznsoValueMethods = &FznsoValueMethods { 366 + kind, 367 + get_decision, 368 + ..*FznsoValueRef::FZNSO_DEFAULT_VALUE_METHODS 369 + }; 370 + 371 + // SAFETY: The value is a &'a FznsoDecisionIdx, and will never be used 372 + // without transmuting back. 373 + let data: &FznsoValue = unsafe { mem::transmute(value) }; 374 + Self { 375 + data, 376 + methods: FZNSO_DECISION_VALUE_METHODS, 377 + } 378 + } 379 + } 380 + 381 + impl TryFrom<&FznsoValueRef<'_>> for bool { 382 + type Error = (); 383 + 384 + fn try_from(value: &FznsoValueRef<'_>) -> Result<Self, Self::Error> { 385 + if (value.methods.kind)(value.data) == FznsoValueKind::FznsoValueBool { 386 + Ok((value.methods.get_bool)(value.data)) 387 + } else { 388 + Err(()) 389 + } 390 + } 391 + } 392 + 393 + impl TryFrom<&FznsoValueRef<'_>> for f64 { 394 + type Error = (); 395 + 396 + fn try_from(value: &FznsoValueRef<'_>) -> Result<Self, Self::Error> { 397 + if value.kind() == FznsoValueKind::FznsoValueFloat { 398 + Ok(value.get_float()) 399 + } else { 400 + Err(()) 401 + } 402 + } 403 + } 404 + 405 + impl TryFrom<&FznsoValueRef<'_>> for i64 { 406 + type Error = (); 407 + 408 + fn try_from(value: &FznsoValueRef<'_>) -> Result<Self, Self::Error> { 409 + if value.kind() == FznsoValueKind::FznsoValueInt { 410 + Ok(value.get_int()) 411 + } else { 412 + Err(()) 413 + } 414 + } 415 + } 416 + 417 + impl<'a> TryFrom<&'a FznsoValueRef<'a>> for &'a ffi::CStr { 418 + type Error = (); 419 + 420 + fn try_from(value: &'a FznsoValueRef<'a>) -> Result<Self, Self::Error> { 421 + if value.kind() == FznsoValueKind::FznsoValueString { 422 + Ok(value.get_string()) 423 + } else { 424 + Err(()) 425 + } 426 + } 427 + } 428 + 429 + impl TryFrom<&FznsoValueRef<'_>> for ffi::CString { 430 + type Error = (); 431 + 432 + fn try_from(value: &FznsoValueRef<'_>) -> Result<Self, Self::Error> { 433 + if value.kind() == FznsoValueKind::FznsoValueString { 434 + Ok(value.get_string().to_owned()) 435 + } else { 436 + Err(()) 437 + } 438 + } 439 + } 440 + 441 + impl TryFrom<&FznsoValueRef<'_>> for FznsoConstraintIdx { 442 + type Error = (); 443 + 444 + fn try_from(value: &FznsoValueRef<'_>) -> Result<Self, Self::Error> { 445 + if value.kind() == FznsoValueKind::FznsoValueConstraint { 446 + Ok(value.get_constraint()) 447 + } else { 448 + Err(()) 449 + } 450 + } 451 + } 452 + 453 + impl TryFrom<&FznsoValueRef<'_>> for FznsoDecisionIdx { 454 + type Error = (); 455 + 456 + fn try_from(value: &FznsoValueRef<'_>) -> Result<Self, Self::Error> { 457 + if value.kind() == FznsoValueKind::FznsoValueDecision { 458 + Ok(value.get_decision()) 459 + } else { 460 + Err(()) 461 + } 462 + } 463 + } 464 + 465 + fznso_value_impls! { i64, f64, bool, FznsoConstraintIdx, FznsoDecisionIdx, ffi::CString }
+14
rust/fznso/Cargo.toml
··· 1 + [package] 2 + name = "fznso" 3 + repository.workspace = true 4 + version.workspace = true 5 + authors.workspace = true 6 + edition.workspace = true 7 + license.workspace = true 8 + 9 + [dependencies] 10 + fznso-types = { path = "../fznso-types" } 11 + libloading = "0.8.9" 12 + 13 + [lints] 14 + workspace = true
+154
rust/fznso/src/lib.rs
··· 1 + //! FZnSO Protocol Library 2 + //! 3 + //! This crate defines an interface for the FZnSO protocol, which allows the 4 + //! incremental usage of solvers that can solve decision and optimization 5 + //! problems. The goal of the interface is to easily use different solvers in a 6 + //! unified way, and to allow the dynamic loading of solver libraries (as DLLs). 7 + 8 + use fznso_types as _; 9 + use libloading as _; 10 + 11 + // use std::{ffi, mem, sync::Arc}; 12 + // use fznso_types::{ 13 + // FznsoConstraintList, FznsoModelRef, FznsoObjectiveList, FznsoOptionList, 14 + // FznsoSolutionRef, FznsoSolver, FznsoStatus, FznsoTypeList, FznsoValueRef, 15 + // }; 16 + // use libloading::Symbol; 17 + 18 + // #[derive(Debug)] 19 + // pub struct Library { 20 + // _lib: libloading::Library, 21 + // constraint_list: Symbol<'static, unsafe extern "C" fn() -> 22 + // FznsoConstraintList<'static>>, decision_list: Symbol<'static, unsafe extern 23 + // "C" fn() -> FznsoTypeList<'static>>, objective_list: Symbol<'static, unsafe 24 + // extern "C" fn() -> FznsoObjectiveList<'static>>, option_list: 25 + // Symbol<'static, unsafe extern "C" fn() -> FznsoOptionList<'static>>, 26 + // solver_create: Symbol<'static, unsafe extern "C" fn() -> *mut FznsoSolver>, 27 + // solver_free: Symbol<'static, unsafe extern "C" fn(*mut FznsoSolver)>, 28 + // solver_option_get: Symbol< 29 + // 'static, 30 + // unsafe extern "C" fn(&FznsoSolver, *const ffi::c_char) -> 31 + // FznsoValueRef<'_>, >, 32 + // solver_option_set: Symbol< 33 + // 'static, 34 + // unsafe extern "C" fn(&FznsoSolver, *const ffi::c_char, FznsoValueRef<'_>) 35 + // -> bool, >, 36 + // solver_read_error: Symbol< 37 + // 'static, 38 + // unsafe extern "C" fn( 39 + // *const FznsoSolver, 40 + // &mut ffi::c_void, 41 + // extern "C" fn(&mut ffi::c_void, *const ffi::c_char), 42 + // ), 43 + // >, 44 + // solver_run: Symbol< 45 + // 'static, 46 + // unsafe extern "C" fn( 47 + // *const FznsoSolver, 48 + // FznsoModelRef, 49 + // &mut ffi::c_void, 50 + // extern "C" fn(&mut ffi::c_void, FznsoSolutionRef), 51 + // ), 52 + // >, 53 + // } 54 + 55 + // /// Methods provided to a [`Solver`] to interact with model instances 56 + // provided /// to be solved. 57 + // pub trait Model {} 58 + 59 + // #[derive(Debug)] 60 + // /// Representation of a solver instance, created from a [`Library`]. 61 + // pub struct Solver { 62 + // solver: *mut FznsoSolver, 63 + // lib: Arc<Library>, 64 + // } 65 + 66 + // /// Methods for interacting with solutions emitted by the solver when running 67 + // a /// model. 68 + // pub trait Solution { 69 + // /// Get the value that a decision, identified using its index, takes in the 70 + // /// solution. 71 + // fn get_value(&self, decision_index: usize) -> FznsoValueRef<'_>; 72 + // } 73 + 74 + // impl Library { 75 + // /// Internal method to get a [`Symbol`] from a library in [`Self::new`]. 76 + // /// 77 + // /// The 78 + // unsafe fn get_symbol<T>( 79 + // lib: &libloading::Library, 80 + // symbol: &[u8], 81 + // ) -> Result<Symbol<'static, T>, libloading::Error> { 82 + // let sym: Symbol<'static, T> = unsafe { 83 + // mem::transmute(lib.get::<T>(symbol)?) }; Ok(sym) 84 + // } 85 + 86 + // /// Creates a new [`Solver`] instance using the functions in the 87 + // /// [`Library`]. 88 + // pub fn create_solver(self: &Arc<Self>) -> Solver { 89 + // let solver = unsafe { (*self.solver_create)() }; 90 + // Solver { 91 + // solver, 92 + // lib: self.clone(), 93 + // } 94 + // } 95 + 96 + // /// Find and load a dynamic FZnSO library. 97 + // /// 98 + // /// Note that this method follows the same conventions as 99 + // /// [`libloading::Library::new`], but in addition also finds and loads the 100 + // /// FZnSO specific symbols. 101 + // pub unsafe fn new<S: AsRef<ffi::OsStr>>(filename: S) -> Result<Arc<Self>, 102 + // libloading::Error> { let lib = unsafe { 103 + // let lib = libloading::Library::new(filename)?; 104 + // let constraint_list = Self::get_symbol(&lib, b"fznso_constraint_list\0")?; 105 + // let decision_list = Self::get_symbol(&lib, b"fznso_decision_list\0")?; 106 + // let objective_list = Self::get_symbol(&lib, b"fznso_objective_list\0")?; 107 + // let option_list = Self::get_symbol(&lib, b"fznso_option_list\0")?; 108 + // let solver_create = Self::get_symbol(&lib, b"fznso_solver_create\0")?; 109 + // let solver_free = Self::get_symbol(&lib, b"fznso_solver_free\0")?; 110 + // let solver_option_get = Self::get_symbol(&lib, 111 + // b"fznso_solver_option_get\0")?; let solver_option_set = 112 + // Self::get_symbol(&lib, b"fznso_solver_option_set\0")?; 113 + // let solver_read_error = Self::get_symbol(&lib, 114 + // b"fznso_solver_read_error\0")?; let solver_run = Self::get_symbol(&lib, 115 + // b"fznso_solver_run\0")?; Self { 116 + // _lib: lib, 117 + // constraint_list, 118 + // decision_list, 119 + // objective_list, 120 + // option_list, 121 + // solver_create, 122 + // solver_free, 123 + // solver_option_get, 124 + // solver_option_set, 125 + // solver_read_error, 126 + // solver_run, 127 + // } 128 + // }; 129 + // Ok(Arc::new(lib)) 130 + // } 131 + // } 132 + 133 + // impl Solver { 134 + // /// Run the given model instance on the solver, calling the provided 135 + // /// callback for each solution found, and returning the status of the run. 136 + // pub fn run( 137 + // &mut self, 138 + // model: impl Model, 139 + // on_solution: impl FnMut(FznsoSolutionRef), 140 + // ) -> FznsoStatus { 141 + // todo!() 142 + // } 143 + // } 144 + 145 + // impl Drop for Solver { 146 + // fn drop(&mut self) { 147 + // unsafe { (*self.lib.solver_free)(self.solver) } 148 + // } 149 + // } 150 + 151 + // unsafe impl Send for Solver {} 152 + 153 + // #[cfg(test)] 154 + // mod tests {}
+2 -2
rust/ipdos-solver-template/Cargo.toml rust/fznso-solver-template/Cargo.toml
··· 1 1 [package] 2 - name = "ipdos-solver-template" 2 + name = "fznso-solver-template" 3 3 repository.workspace = true 4 4 version.workspace = true 5 5 authors.workspace = true ··· 12 12 crate-type = ["cdylib"] 13 13 14 14 [dependencies] 15 - ipdos-types = { path = "../ipdos-types" } 15 + fznso-types = { path = "../fznso-types" } 16 16 17 17 [lints] 18 18 workspace = true
+29 -29
rust/ipdos-solver-template/src/lib.rs rust/fznso-solver-template/src/lib.rs
··· 1 - //! IPDOS Protocol Solver Template 1 + //! FZnSO Protocol Solver Template 2 2 //! 3 - //! This crate defines the solver functionality to be implemented IPDOS 3 + //! This crate defines the solver functionality to be implemented FZnSO 4 4 //! protocol, which allows the incremental usage of solvers that can solve 5 5 //! decision and optimization problems. The goal of the interface is to easily 6 6 //! use different solvers in a unified way, and to allow the dynamic loading of ··· 8 8 9 9 use core::ffi; 10 10 11 - use ipdos_types::{ 12 - IpdosConstraintList, IpdosModelRef, IpdosObjectiveList, IpdosOptionList, IpdosSolutionRef, 13 - IpdosSolver, IpdosStatisticList, IpdosStatus, IpdosTypeList, IpdosValueRef, 11 + use fznso_types::{ 12 + FznsoConstraintList, FznsoModelRef, FznsoObjectiveList, FznsoOptionList, FznsoSolutionRef, 13 + FznsoSolver, FznsoStatisticList, FznsoStatus, FznsoTypeList, FznsoValueRef, 14 14 }; 15 15 16 16 #[unsafe(no_mangle)] 17 17 /// Returns the list of available constraint that can be added to the solver. 18 - pub extern "C" fn ipdos_constraint_list() -> IpdosConstraintList<'static> { 18 + pub extern "C" fn fznso_constraint_list() -> FznsoConstraintList<'static> { 19 19 unimplemented!() 20 20 } 21 21 22 22 #[unsafe(no_mangle)] 23 23 /// Returns the list of types for which decision variable can be created by the 24 24 /// solver. 25 - pub extern "C" fn ipdos_decision_list() -> IpdosTypeList<'static> { 25 + pub extern "C" fn fznso_decision_list() -> FznsoTypeList<'static> { 26 26 unimplemented!() 27 27 } 28 28 29 29 #[unsafe(no_mangle)] 30 30 /// Returns the list of available objective that can be achieved by the solver. 31 - pub extern "C" fn ipdos_objective_list() -> IpdosObjectiveList<'static> { 31 + pub extern "C" fn fznso_objective_list() -> FznsoObjectiveList<'static> { 32 32 unimplemented!() 33 33 } 34 34 35 35 #[unsafe(no_mangle)] 36 36 /// Returns the list of available options that can be set of the solver. 37 - pub extern "C" fn ipdos_option_list() -> IpdosOptionList<'static> { 37 + pub extern "C" fn fznso_option_list() -> FznsoOptionList<'static> { 38 38 unimplemented!() 39 39 } 40 40 41 41 #[unsafe(no_mangle)] 42 42 /// Create a new solver instance 43 - pub extern "C" fn ipdos_solver_create() -> *mut IpdosSolver { 43 + pub extern "C" fn fznso_solver_create() -> *mut FznsoSolver { 44 44 unimplemented!() 45 45 } 46 46 ··· 49 49 /// The pointer to the solver instance will be invalid after this function has 50 50 /// been called. 51 51 #[unsafe(no_mangle)] 52 - pub extern "C" fn ipdos_solver_free(solver: *mut IpdosSolver) { 52 + pub extern "C" fn fznso_solver_free(solver: *mut FznsoSolver) { 53 53 let _ = solver; 54 54 unimplemented!() 55 55 } ··· 58 58 /// Get the current value of an option for the solver. 59 59 /// 60 60 /// Note that this is only valid to be called with options named by 61 - /// `ipdos_option_list`. 62 - pub extern "C" fn ipdos_solver_option_get( 63 - solver: &IpdosSolver, 61 + /// `fznso_option_list`. 62 + pub extern "C" fn fznso_solver_option_get( 63 + solver: &FznsoSolver, 64 64 ident: *const ffi::c_char, 65 - ) -> IpdosValueRef<'_> { 65 + ) -> FznsoValueRef<'_> { 66 66 let _ = solver; 67 67 let _ = ident; 68 68 unimplemented!() ··· 72 72 /// Set the current value of an option for the solver. 73 73 /// 74 74 /// Note that this is only valid to be called with options named by 75 - /// `ipdos_option_list`, and the value must be of the correct type. 76 - pub extern "C" fn ipdos_solver_option_set( 77 - solver: &mut IpdosSolver, 75 + /// `fznso_option_list`, and the value must be of the correct type. 76 + pub extern "C" fn fznso_solver_option_set( 77 + solver: &mut FznsoSolver, 78 78 ident: *const ffi::c_char, 79 - value: IpdosValueRef<'_>, 79 + value: FznsoValueRef<'_>, 80 80 ) -> bool { 81 81 let _ = solver; 82 82 let _ = ident; ··· 88 88 /// Read an error message from the solver. 89 89 /// 90 90 /// This function is expected to be called after solver interactions signal an 91 - /// error has occurred. For example, if [`ipdos_solver_run`] returns 92 - /// [`IpdosError`] or [`ipdos_solver_push`] returns `false`. 93 - pub extern "C" fn ipdos_solver_read_error( 94 - solver: &mut IpdosSolver, 91 + /// error has occurred. For example, if [`fznso_solver_run`] returns 92 + /// [`FznsoError`] or [`fznso_solver_push`] returns `false`. 93 + pub extern "C" fn fznso_solver_read_error( 94 + solver: &mut FznsoSolver, 95 95 context: &mut ffi::c_void, 96 96 read_error: extern "C" fn(context: &mut ffi::c_void, error: *const ffi::c_char), 97 97 ) { ··· 103 103 104 104 #[unsafe(no_mangle)] 105 105 /// Run the solver with the given model 106 - pub extern "C" fn ipdos_solver_run( 107 - solver: &mut IpdosSolver, 108 - model: IpdosModelRef, 106 + pub extern "C" fn fznso_solver_run( 107 + solver: &mut FznsoSolver, 108 + model: FznsoModelRef, 109 109 context: &mut ffi::c_void, 110 - on_solution: extern "C" fn(context: &mut ffi::c_void, solution: IpdosSolutionRef), 111 - ) -> IpdosStatus { 110 + on_solution: extern "C" fn(context: &mut ffi::c_void, solution: FznsoSolutionRef), 111 + ) -> FznsoStatus { 112 112 let _ = solver; 113 113 let _ = model; 114 114 let _ = context; ··· 119 119 #[unsafe(no_mangle)] 120 120 /// Returns the list of available statistical information that can be requested 121 121 /// from the solver and its solutions. 122 - pub extern "C" fn ipdos_statistic_list() -> IpdosStatisticList<'static> { 122 + pub extern "C" fn fznso_statistic_list() -> FznsoStatisticList<'static> { 123 123 unimplemented!() 124 124 }
+1 -1
rust/ipdos-types/Cargo.toml rust/fznso-types/Cargo.toml
··· 1 1 [package] 2 - name = "ipdos-types" 2 + name = "fznso-types" 3 3 repository.workspace = true 4 4 version.workspace = true 5 5 authors.workspace = true
+193 -193
rust/ipdos-types/src/lib.rs rust/fznso-types/src/lib.rs
··· 1 - //! IPDOS Protocol Types 1 + //! FZnSO Protocol Types 2 2 //! 3 - //! This crate defines the types of the IPDOS protocol, which allows the 3 + //! This crate defines the types of the FZnSO protocol, which allows the 4 4 //! incremental usage of solvers that can solve decision and optimization 5 5 //! problems. The goal of the interface is to easily use different solvers in a 6 6 //! unified way, and to allow the dynamic loading of solver libraries (as DLLs). ··· 15 15 /// 16 16 /// This type is opaque to the user. Only pointers of this type are ever used. 17 17 /// 18 - /// In implementation of the IPDOS interface, a pointer is generally cast to 19 - /// this type, i.e. `(IpdosSolutionData*) my_solution`. A similar cast can be 18 + /// In implementation of the FZnSO interface, a pointer is generally cast to 19 + /// this type, i.e. `(FznsoSolutionData*) my_solution`. A similar cast can be 20 20 /// used to cast the pointer back to the original type, e.g. `(MySolution*) 21 - /// ipdos_solution`. 22 - pub struct IpdosAnnotation(ffi::c_void); 21 + /// fznso_solution`. 22 + pub struct FznsoAnnotation(ffi::c_void); 23 23 24 24 #[repr(transparent)] 25 25 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] 26 26 /// Wrapper type for the indexes that represent constraints in the model. 27 - pub struct IpdosConstraintIdx(pub usize); 27 + pub struct FznsoConstraintIdx(pub usize); 28 28 29 29 #[repr(C)] 30 30 #[derive(Clone, Debug)] 31 - /// A list of [`IpdosConstraintType`]s. 31 + /// A list of [`FznsoConstraintType`]s. 32 32 /// 33 - /// This type is for example used to return from [`ipdos_constraint_list`]. 34 - pub struct IpdosConstraintList<'a> { 33 + /// This type is for example used to return from [`fznso_constraint_list`]. 34 + pub struct FznsoConstraintList<'a> { 35 35 /// The number of elements in the `constraints` array. 36 36 pub len: usize, 37 37 /// An array of constraint types. 38 - pub constraints: *const IpdosConstraintType<'a>, 38 + pub constraints: *const FznsoConstraintType<'a>, 39 39 /// The lifetime for which the `constraints` attribute is allocated. 40 40 pub lifetime: PhantomData<&'a ()>, 41 41 } ··· 44 44 #[derive(Clone, Debug)] 45 45 /// Representation of a type of constraint, discerned by its identifier and the 46 46 /// types of its arguments. 47 - pub struct IpdosConstraintType<'a> { 47 + pub struct FznsoConstraintType<'a> { 48 48 /// The identifier of the constraint type. 49 49 pub ident: *const ffi::c_char, 50 50 /// The number of expected arguments for the constraint type. 51 51 pub arg_len: usize, 52 52 /// The types of the expected arguments for the constraint type. 53 - pub arg_types: *const IpdosType, 53 + pub arg_types: *const FznsoType, 54 54 /// The lifetime for which the `ident` and `arg_types` attributes are 55 55 /// allocated. 56 56 pub lifetime: PhantomData<&'a ()>, ··· 59 59 #[repr(transparent)] 60 60 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] 61 61 /// Wrapper type for the indexes that represent decision variables in the model. 62 - pub struct IpdosDecisionIdx(pub usize); 62 + pub struct FznsoDecisionIdx(pub usize); 63 63 64 64 #[repr(transparent)] 65 65 #[derive(Debug)] ··· 67 67 /// 68 68 /// This type is opaque to the user. Only pointers of this type are ever used. 69 69 /// 70 - /// In implementation of the IPDOS interface, a pointer is generally cast to 71 - /// this type, i.e. `(IpdosModelData*) my_model`. A similar cast can be used to 72 - /// cast the pointer back to the original type, e.g. `(MyModel*) ipdos_model`. 73 - pub struct IpdosModel(ffi::c_void); 70 + /// In implementation of the FZnSO interface, a pointer is generally cast to 71 + /// this type, i.e. `(FznsoModelData*) my_model`. A similar cast can be used to 72 + /// cast the pointer back to the original type, e.g. `(MyModel*) fznso_model`. 73 + pub struct FznsoModel(ffi::c_void); 74 74 75 75 #[repr(C)] 76 76 #[derive(Debug)] 77 77 /// A struct containing the function pointers to interact with the 78 - /// [`IpdosModel`] 79 - pub struct IpdosModelMethods { 78 + /// [`FznsoModel`] 79 + pub struct FznsoModelMethods { 80 80 /// Returns the current number of model layers currently contained in the 81 81 /// model. 82 82 /// 83 83 /// Layers provides a way for the modelling user to add and retract 84 - layer_len: extern "C" fn(model: &IpdosModel) -> usize, 84 + layer_len: extern "C" fn(model: &FznsoModel) -> usize, 85 85 /// Returns the number of layers that have been unchanged since the last 86 - /// call to [`ipdos_solver_run`]. 86 + /// call to [`fznso_solver_run`]. 87 87 /// 88 88 /// Unchanged layers must be consecutive starting from layer 0. 89 - layer_unchanged: extern "C" fn(model: &IpdosModel) -> usize, 89 + layer_unchanged: extern "C" fn(model: &FznsoModel) -> usize, 90 90 /// Returns the number of permanent layers in the model. 91 91 /// 92 92 /// Permanent layers are laid out must be consecutive starting from layer 0. ··· 97 97 /// the solver to remove the decision variables and constraints in these 98 98 /// layers, if convenient. This is signaled using [`layer_redundant_len`] 99 99 /// and [`layer_redundant_index`]. 100 - layer_permanent: extern "C" fn(model: &IpdosModel) -> usize, 100 + layer_permanent: extern "C" fn(model: &FznsoModel) -> usize, 101 101 /// Returns the number of permanent layers that have been marked as 102 102 /// redundant. 103 103 /// ··· 105 105 /// layers, if convenient. Once a layer is marked as redundant, it can 106 106 /// forever be considered redundant. As such, the solver can assume that 107 107 /// the number of redundant layers only ever increases. 108 - layer_redundant_len: extern "C" fn(model: &IpdosModel) -> usize, 108 + layer_redundant_len: extern "C" fn(model: &FznsoModel) -> usize, 109 109 /// Returns the index of the n-th permanent layer that has been marked as 110 110 /// redundant. 111 111 /// 112 112 /// The `n` argument must be less than the value returned by 113 113 /// [`layer_redundant_len`]. 114 - layer_redundant_index: extern "C" fn(model: &IpdosModel, n: usize) -> usize, 114 + layer_redundant_index: extern "C" fn(model: &FznsoModel, n: usize) -> usize, 115 115 116 116 /// Retrieve the number of decisions currently contained in the model. 117 - decision_len: extern "C" fn(model: &IpdosModel) -> usize, 117 + decision_len: extern "C" fn(model: &FznsoModel) -> usize, 118 118 /// Retrieve the decision index of the last decision variable in the layer. 119 119 /// 120 120 /// This can be equivalent to `decision_layer_end` of `layer-1` if the layer 121 121 /// does not add any new decisions. 122 - decision_layer_end: extern "C" fn(model: &IpdosModel, layer: usize) -> usize, 122 + decision_layer_end: extern "C" fn(model: &FznsoModel, layer: usize) -> usize, 123 123 /// Retrieve the domain of the given decision. 124 124 /// 125 - /// Note that the the value might have [`IpdosValueKind::IpdosValueAbsent`] 125 + /// Note that the the value might have [`FznsoValueKind::FznsoValueAbsent`] 126 126 /// if the decision variable does not have an explicit domain. 127 127 decision_domain: 128 - extern "C" fn(model: &IpdosModel, decision: IpdosDecisionIdx) -> IpdosValueRef<'_>, 128 + extern "C" fn(model: &FznsoModel, decision: FznsoDecisionIdx) -> FznsoValueRef<'_>, 129 129 /// Retrieve the name of a decision variable, if it exists. 130 130 /// 131 131 /// Note that names are only available for debugging purposes. Decisions are 132 132 /// identified using their index in the model. If the decision variable does 133 133 /// not have a name, this function returns a null pointer. 134 134 decision_name: 135 - extern "C" fn(model: &IpdosModel, decision: IpdosDecisionIdx) -> *const ffi::c_char, 135 + extern "C" fn(model: &FznsoModel, decision: FznsoDecisionIdx) -> *const ffi::c_char, 136 136 /// Check whether the decision variable is defined by a constraint. 137 - decision_defined: extern "C" fn(model: &IpdosModel, decision: IpdosDecisionIdx) -> bool, 137 + decision_defined: extern "C" fn(model: &FznsoModel, decision: FznsoDecisionIdx) -> bool, 138 138 /// Retrieve the number of annotations of a constraint. 139 - decision_annotation_len: extern "C" fn(model: &IpdosModel, decision: IpdosDecisionIdx) -> usize, 139 + decision_annotation_len: extern "C" fn(model: &FznsoModel, decision: FznsoDecisionIdx) -> usize, 140 140 /// Retrieve the value of the constraint's annotation at the given index. 141 141 /// 142 142 /// The `index` argument must be less than the value returned by 143 143 /// [`decision_annotation_len`] for the given decision variable. 144 144 decision_annotation: extern "C" fn( 145 - model: &IpdosModel, 146 - decision: IpdosDecisionIdx, 145 + model: &FznsoModel, 146 + decision: FznsoDecisionIdx, 147 147 index: usize, 148 - ) -> &IpdosAnnotation, 148 + ) -> &FznsoAnnotation, 149 149 150 150 /// Retrieve the number of constraints currently contained in the model. 151 - constraint_len: extern "C" fn(model: &IpdosModel) -> usize, 151 + constraint_len: extern "C" fn(model: &FznsoModel) -> usize, 152 152 /// Retrieve the constraint index of the first new constraint in the layer. 153 153 /// 154 154 /// This can be equivalent to `constraint_len` if the layer does not add any 155 155 /// new constraints. 156 - constraint_layer_end: extern "C" fn(model: &IpdosModel) -> usize, 156 + constraint_layer_end: extern "C" fn(model: &FznsoModel) -> usize, 157 157 /// Retrieve the identifier of a constraint. 158 158 /// 159 159 /// The returned pointer can be assumed to have the the same lifetime as the 160 160 /// model reference and must be valid UTF8. 161 161 constraint_ident: 162 - extern "C" fn(model: &IpdosModel, constraint: IpdosConstraintIdx) -> *const ffi::c_char, 162 + extern "C" fn(model: &FznsoModel, constraint: FznsoConstraintIdx) -> *const ffi::c_char, 163 163 /// Retrieve the number of arguments of a constraint. 164 164 constraint_argument_len: 165 - extern "C" fn(model: &IpdosModel, constraint: IpdosConstraintIdx) -> usize, 165 + extern "C" fn(model: &FznsoModel, constraint: FznsoConstraintIdx) -> usize, 166 166 /// Retrieve the value of the constraint's argument at the given index. 167 167 /// 168 168 /// The `index` argument must be less than the value returned by 169 169 /// `constraint_argument_len` for the given constraint. 170 170 constraint_argument: extern "C" fn( 171 - model: &IpdosModel, 172 - constraint: IpdosConstraintIdx, 171 + model: &FznsoModel, 172 + constraint: FznsoConstraintIdx, 173 173 index: usize, 174 - ) -> IpdosValueRef<'_>, 174 + ) -> FznsoValueRef<'_>, 175 175 /// Check whether the decision variable is functionally defined by a 176 176 /// constraint. 177 177 /// 178 - /// This function returns a [`IpdosValue`] that is either 179 - /// [`IpdosValueKind::IpdosValueDecision`] if it defined a decision variable 180 - /// or [`IpdosValueKind::IpdosValueAbsent`] otherwise. 178 + /// This function returns a [`FznsoValue`] that is either 179 + /// [`FznsoValueKind::FznsoValueDecision`] if it defined a decision variable 180 + /// or [`FznsoValueKind::FznsoValueAbsent`] otherwise. 181 181 constraint_defines: 182 - extern "C" fn(model: &IpdosModel, constraint: IpdosConstraintIdx) -> IpdosValueRef<'_>, 182 + extern "C" fn(model: &FznsoModel, constraint: FznsoConstraintIdx) -> FznsoValueRef<'_>, 183 183 /// Retrieve the number of annotations on a constraint. 184 184 constraint_annotation_len: 185 - extern "C" fn(model: &IpdosModel, constraint: IpdosConstraintIdx) -> usize, 185 + extern "C" fn(model: &FznsoModel, constraint: FznsoConstraintIdx) -> usize, 186 186 /// Retrieve the annotation on a constraint at the given index. 187 187 /// 188 188 /// The `index` argument must be less than the value returned by 189 189 /// `constraint_annotation_len` for the given constraint. 190 190 constraint_annotation: extern "C" fn( 191 - model: &IpdosModel, 192 - constraint: IpdosConstraintIdx, 191 + model: &FznsoModel, 192 + constraint: FznsoConstraintIdx, 193 193 index: usize, 194 - ) -> &IpdosAnnotation, 194 + ) -> &FznsoAnnotation, 195 195 196 196 /// Request the identifier of the type of objective strategy to be used when 197 197 /// solving the model. 198 198 /// 199 199 /// Note that the function can return a null pointer if the model does not 200 200 /// have an objective strategy. 201 - objective_ident: extern "C" fn(model: &IpdosModel) -> *const ffi::c_char, 201 + objective_ident: extern "C" fn(model: &FznsoModel) -> *const ffi::c_char, 202 202 /// Retrieve the argument of the objective strategy. 203 - objective_arg: extern "C" fn(model: &IpdosModel) -> IpdosValueRef<'_>, 203 + objective_arg: extern "C" fn(model: &FznsoModel) -> FznsoValueRef<'_>, 204 204 /// Retrieve the number of annotations on an objective 205 - objective_annotation_len: extern "C" fn(model: &IpdosModel) -> usize, 205 + objective_annotation_len: extern "C" fn(model: &FznsoModel) -> usize, 206 206 /// Retrieve the annotation on the objective at the given index. 207 207 /// 208 208 /// The `index` argument must be less than the value returned by 209 209 /// `objective_annotation_len`. 210 - objective_annotation: extern "C" fn(model: &IpdosModel, index: usize) -> &IpdosAnnotation, 210 + objective_annotation: extern "C" fn(model: &FznsoModel, index: usize) -> &FznsoAnnotation, 211 211 212 212 /// Retrieve the identifier of an annotation. 213 213 /// 214 214 /// The returned pointer can be assumed to have the the same lifetime as the 215 215 /// annotation reference and must be valid UTF8. 216 - annotation_ident: extern "C" fn(ann: &IpdosAnnotation) -> *const ffi::c_char, 216 + annotation_ident: extern "C" fn(ann: &FznsoAnnotation) -> *const ffi::c_char, 217 217 /// Retrieve the number of arguments of an annotation. 218 - annotation_argument_len: extern "C" fn(ann: &IpdosAnnotation) -> usize, 218 + annotation_argument_len: extern "C" fn(ann: &FznsoAnnotation) -> usize, 219 219 /// Retrieve the value of the annotation's argument at the given index. 220 220 /// 221 221 /// The `index` argument must be less than the value returned by 222 222 /// `annotation_argument_len` for the given annotation. 223 - annotation_argument: extern "C" fn(ann: &IpdosAnnotation, index: usize) -> IpdosValueRef<'_>, 223 + annotation_argument: extern "C" fn(ann: &FznsoAnnotation, index: usize) -> FznsoValueRef<'_>, 224 224 } 225 225 226 226 #[repr(C)] ··· 229 229 /// 230 230 /// The solver can use the included function callbacks to interact with the 231 231 /// model. 232 - pub struct IpdosModelRef<'a> { 232 + pub struct FznsoModelRef<'a> { 233 233 /// The handle to the data of the model instance. 234 - data: &'a IpdosModel, 234 + data: &'a FznsoModel, 235 235 /// Reference to the structure containing the function callbacks used to 236 236 /// interact with the model. 237 - methods: &'static IpdosModelMethods, 237 + methods: &'static FznsoModelMethods, 238 238 } 239 239 240 240 #[repr(C)] 241 241 #[derive(Clone, Debug)] 242 242 /// Representation of a type of objective strategies, discerned by its 243 243 /// identifier and the type of its argument. 244 - pub struct IpdosObjective<'a> { 244 + pub struct FznsoObjective<'a> { 245 245 /// The identifier of the objective type. 246 246 pub ident: *const ffi::c_char, 247 247 /// The type of the expected argument for the constraint type. 248 - pub arg_type: IpdosType, 248 + pub arg_type: FznsoType, 249 249 /// The lifetime for which the `ident` attribute is allocated. 250 250 pub lifetime: PhantomData<&'a ()>, 251 251 } 252 252 253 253 #[repr(C)] 254 254 #[derive(Clone, Debug)] 255 - /// A list of [`IpdosObjective`]s. 255 + /// A list of [`FznsoObjective`]s. 256 256 /// 257 - /// This type is, for example, used to return from [`ipdos_objective_list`]. 258 - pub struct IpdosObjectiveList<'a> { 257 + /// This type is, for example, used to return from [`fznso_objective_list`]. 258 + pub struct FznsoObjectiveList<'a> { 259 259 /// The number of elements in the `options` array. 260 260 pub len: usize, 261 261 /// An array of option definitions. 262 - pub options: *const IpdosObjective<'a>, 262 + pub options: *const FznsoObjective<'a>, 263 263 /// The lifetime of the `options` attribute. 264 264 pub lifetime: PhantomData<&'a ()>, 265 265 } ··· 267 267 #[repr(C)] 268 268 #[derive(Clone, Debug)] 269 269 /// The definition of an option that is available to be set for the solver. 270 - pub struct IpdosOption<'a> { 270 + pub struct FznsoOption<'a> { 271 271 /// The identifier used to set the option or get the current value of the 272 272 /// option. 273 273 pub ident: *const ffi::c_char, 274 274 /// The type of value that is expected for this option. 275 - pub arg_ty: IpdosValueRef<'a>, 275 + pub arg_ty: FznsoValueRef<'a>, 276 276 /// The default value for this option. 277 - pub arg_def: IpdosType, 277 + pub arg_def: FznsoType, 278 278 /// The lifetime of the `ident` attribute. 279 279 pub lifetime: PhantomData<&'a ()>, 280 280 } 281 281 282 282 #[repr(C)] 283 283 #[derive(Clone, Debug)] 284 - /// A list of [`IpdosOption`]s. 284 + /// A list of [`FznsoOption`]s. 285 285 /// 286 - /// This type is, for example, used to return from [`ipdos_option_list`]. 287 - pub struct IpdosOptionList<'a> { 286 + /// This type is, for example, used to return from [`fznso_option_list`]. 287 + pub struct FznsoOptionList<'a> { 288 288 /// The number of elements in the `options` array. 289 289 pub len: usize, 290 290 /// An array of option definitions. 291 - pub options: *const IpdosOption<'a>, 291 + pub options: *const FznsoOption<'a>, 292 292 /// The lifetime of the `options` attribute. 293 293 pub lifetime: PhantomData<&'a ()>, 294 294 } ··· 299 299 /// 300 300 /// This type is opaque to the user. Only pointers of this type are ever used. 301 301 /// 302 - /// In implementation of the IPDOS interface, a pointer is generally cast to 303 - /// this type, i.e. `(IpdosSolutionData*) my_solution`. A similar cast can be 302 + /// In implementation of the FZnSO interface, a pointer is generally cast to 303 + /// this type, i.e. `(FznsoSolutionData*) my_solution`. A similar cast can be 304 304 /// used to cast the pointer back to the original type, e.g. `(MySolution*) 305 - /// ipdos_solution`. 306 - pub struct IpdosSolution(ffi::c_void); 305 + /// fznso_solution`. 306 + pub struct FznsoSolution(ffi::c_void); 307 307 308 308 #[repr(C)] 309 309 #[derive(Clone, Debug)] 310 310 /// A struct containing the function pointers to interact with a 311 - /// [`IpdosSolution`] 312 - pub struct IpdosSolutionMethods { 311 + /// [`FznsoSolution`] 312 + pub struct FznsoSolutionMethods { 313 313 /// Function callback to retrieve the value assigned to a decision variable 314 314 /// in the solution. 315 - get_value: extern "C" fn(data: &IpdosSolution, decision_index: usize) -> IpdosValueRef<'_>, 315 + get_value: extern "C" fn(data: &FznsoSolution, decision_index: usize) -> FznsoValueRef<'_>, 316 316 /// Function callback to retrieve the statistical information made available 317 317 /// by the solver about the search process so far. 318 318 get_statistic: 319 - extern "C" fn(data: &IpdosSolution, ident: *const ffi::c_char) -> IpdosValueRef<'_>, 319 + extern "C" fn(data: &FznsoSolution, ident: *const ffi::c_char) -> FznsoValueRef<'_>, 320 320 } 321 321 322 322 #[repr(C)] 323 323 #[derive(Clone, Debug)] 324 324 /// Handle for a solution emitted by the solver. 325 - pub struct IpdosSolutionRef<'a> { 325 + pub struct FznsoSolutionRef<'a> { 326 326 /// The data pointer to be the first argument of `get_value`. 327 - data: &'a IpdosSolution, 327 + data: &'a FznsoSolution, 328 328 /// Reference to the structure containing the function callbacks used to 329 329 /// interact with the solution. 330 - methods: &'static IpdosSolutionMethods, 330 + methods: &'static FznsoSolutionMethods, 331 331 } 332 332 333 333 #[repr(transparent)] ··· 336 336 /// 337 337 /// This type is opaque to the user. Only pointers of this type are ever used. 338 338 /// 339 - /// In implementation of the IPDOS interface, a pointer is generally cast to 340 - /// this type, i.e. `(IpdosSolver*) my_solver`. A similar cast can be used to 339 + /// In implementation of the FZnSO interface, a pointer is generally cast to 340 + /// this type, i.e. `(FznsoSolver*) my_solver`. A similar cast can be used to 341 341 /// cast the pointer back to the original type, e.g. `(MySolverType*) 342 - /// ipdos_solver`. 343 - pub struct IpdosSolver(ffi::c_void); 342 + /// fznso_solver`. 343 + pub struct FznsoSolver(ffi::c_void); 344 344 345 345 #[repr(C)] 346 346 #[derive(Clone, Debug)] 347 347 /// The definition of statistical information that is made available by the 348 348 /// solver. 349 - pub struct IpdosStatistic<'a> { 349 + pub struct FznsoStatistic<'a> { 350 350 /// The identifier used to retrieve the statistical information from the 351 351 /// solver or a solution. 352 352 pub ident: *const ffi::c_char, 353 353 /// The type of value that is expected for this option. 354 - pub ty: IpdosValueRef<'a>, 354 + pub ty: FznsoValueRef<'a>, 355 355 /// Whether the statistical information is available as part of solutions. 356 356 pub solution: bool, 357 357 /// Whether the statistical information is generally available from the ··· 363 363 364 364 #[repr(C)] 365 365 #[derive(Clone, Debug)] 366 - /// A list of [`IpdosStatistic`]s. 366 + /// A list of [`FznsoStatistic`]s. 367 367 /// 368 - /// This type is, for example, used to return from [`ipdos_statistic_list`]. 369 - pub struct IpdosStatisticList<'a> { 368 + /// This type is, for example, used to return from [`fznso_statistic_list`]. 369 + pub struct FznsoStatisticList<'a> { 370 370 /// The number of elements in the `stats` array. 371 371 pub len: usize, 372 372 /// An array of statistical information definitions. 373 - pub stats: *const IpdosStatistic<'a>, 373 + pub stats: *const FznsoStatistic<'a>, 374 374 /// The lifetime of the `stats` attribute. 375 375 pub lifetime: PhantomData<&'a ()>, 376 376 } 377 377 378 378 #[repr(C)] 379 379 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 380 - /// The status returned by `ipdos_solver_run`, indicating whether the solver 380 + /// The status returned by `fznso_solver_run`, indicating whether the solver 381 381 /// completed its search. 382 - pub enum IpdosStatus { 382 + pub enum FznsoStatus { 383 383 /// The solver explored the full search space and yielded all relevant 384 384 /// solutions. 385 - IpdosComplete, 385 + FznsoComplete, 386 386 /// The solver did not explore the full search space due to a timeout or 387 387 /// other termination condition. Additional (better) solutions might be 388 388 /// possible. 389 - IpdosIncomplete, 389 + FznsoIncomplete, 390 390 /// An error occurred during the solver's execution. 391 391 /// 392 - /// [`ipdos_solver_read_error`] can be used to retrieve the error message. 393 - IpdosError, 392 + /// [`fznso_solver_read_error`] can be used to retrieve the error message. 393 + FznsoError, 394 394 } 395 395 396 396 #[repr(C)] 397 397 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 398 398 /// Representation of a type to signal and check whether an argument takes the 399 399 /// correct type. 400 - pub struct IpdosType { 400 + pub struct FznsoType { 401 401 /// Whether the type is a list of values. 402 402 pub list_of: bool, 403 403 /// Whether the argument can be or contain decision variables (represented ··· 406 406 /// Whether expected type is an set of values of the base type. 407 407 pub set_of: bool, 408 408 /// Whether the expected type is optional (and can take the value of 409 - /// [`IpdosValueKind::IpdosValueAbsent`]). 409 + /// [`FznsoValueKind::FznsoValueAbsent`]). 410 410 pub opt: bool, 411 411 /// The expected base type of the argument. 412 - pub base: IpdosTypeBase, 412 + pub base: FznsoTypeBase, 413 413 } 414 414 415 415 #[repr(C)] 416 416 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 417 417 /// Representation of the base type of a value. 418 - pub enum IpdosTypeBase { 418 + pub enum FznsoTypeBase { 419 419 /// Boolean type 420 - IpdosTypeBaseBool, 420 + FznsoTypeBaseBool, 421 421 /// Integer numeric type 422 - IpdosTypeBaseInt, 422 + FznsoTypeBaseInt, 423 423 /// Floating point numeric type 424 - IpdosTypeBaseFloat, 424 + FznsoTypeBaseFloat, 425 425 /// Character string type 426 - IpdosTypeBaseString, 426 + FznsoTypeBaseString, 427 427 } 428 428 429 429 #[repr(C)] 430 430 #[derive(Clone, Debug)] 431 - /// A list of [`IpdosType`]s. 431 + /// A list of [`FznsoType`]s. 432 432 /// 433 - /// This type is for example used to return from [`ipdos_decision_list`]. 434 - pub struct IpdosTypeList<'a> { 433 + /// This type is for example used to return from [`fznso_decision_list`]. 434 + pub struct FznsoTypeList<'a> { 435 435 /// The number of elements in the `constraints` array. 436 436 pub len: usize, 437 437 /// An array of constraint types. 438 - pub types: *const IpdosType, 438 + pub types: *const FznsoType, 439 439 /// The lifetime for which the `types` attribute is allocated. 440 440 pub lifetime: PhantomData<&'a ()>, 441 441 } ··· 446 446 /// 447 447 /// This type is opaque to the user. Only pointers of this type are ever used. 448 448 /// 449 - /// In implementation of the IPDOS interface, a pointer is generally cast to 450 - /// this type, e.g. `(IpdosValue*) my_value`. A similar cast can be used to cast 451 - /// the pointer back to the original type, e.g. `(MyValue*) ipdos_value`. 452 - pub struct IpdosValue(ffi::c_void); 449 + /// In implementation of the FZnSO interface, a pointer is generally cast to 450 + /// this type, e.g. `(FznsoValue*) my_value`. A similar cast can be used to cast 451 + /// the pointer back to the original type, e.g. `(MyValue*) fznso_value`. 452 + pub struct FznsoValue(ffi::c_void); 453 453 454 454 #[repr(C)] 455 455 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 456 - /// Enumerated type used to mark the kind of [`IpdosValue`]. This is used to 457 - /// determine which "get" method in [`IpdosValueMethods`] is safe to call. 458 - pub enum IpdosValueKind { 456 + /// Enumerated type used to mark the kind of [`FznsoValue`]. This is used to 457 + /// determine which "get" method in [`FznsoValueMethods`] is safe to call. 458 + pub enum FznsoValueKind { 459 459 /// No value is available. 460 - IpdosValueAbsent, 461 - /// The value is available using [`IpdosValueMethods::get_decision`]. 462 - IpdosValueDecision, 463 - /// The value is available using [`IpdosValueMethods::get_constraint`]. 464 - IpdosValueConstraint, 465 - /// The value is available using [`IpdosValueMethods::get_bool`]. 466 - IpdosValueBool, 467 - /// The value is available using [`IpdosValueMethods::get_int`]. 468 - IpdosValueInt, 469 - /// The value is available using [`IpdosValueMethods::get_float`]. 470 - IpdosValueFloat, 471 - /// The value is available using [`IpdosValueMethods::get_string`]. 472 - IpdosValueString, 460 + FznsoValueAbsent, 461 + /// The value is available using [`FznsoValueMethods::get_decision`]. 462 + FznsoValueDecision, 463 + /// The value is available using [`FznsoValueMethods::get_constraint`]. 464 + FznsoValueConstraint, 465 + /// The value is available using [`FznsoValueMethods::get_bool`]. 466 + FznsoValueBool, 467 + /// The value is available using [`FznsoValueMethods::get_int`]. 468 + FznsoValueInt, 469 + /// The value is available using [`FznsoValueMethods::get_float`]. 470 + FznsoValueFloat, 471 + /// The value is available using [`FznsoValueMethods::get_string`]. 472 + FznsoValueString, 473 473 /// Sets of integers are represented using a range list. The number of 474 - /// ranges is available using [`IpdosValueMethods::len`], and the ranges can 475 - /// be accessed using [`IpdosValueMethods::get_range_int`]. 476 - IpdosValueSetInt, 474 + /// ranges is available using [`FznsoValueMethods::len`], and the ranges can 475 + /// be accessed using [`FznsoValueMethods::get_range_int`]. 476 + FznsoValueSetInt, 477 477 /// Sets of floats are represented using a range list. The number of 478 - /// ranges is available using [`IpdosValueMethods::len`], and the ranges can 479 - /// be accessed using [`IpdosValueMethods::get_range_float`]. 480 - IpdosValueSetFloat, 478 + /// ranges is available using [`FznsoValueMethods::len`], and the ranges can 479 + /// be accessed using [`FznsoValueMethods::get_range_float`]. 480 + FznsoValueSetFloat, 481 481 /// The length of the list can be accessed using 482 - /// [`IpdosValueMethods::len`], and elements in the list can be 483 - /// accessed using [`IpdosValueMethods::get_element`] 484 - IpdosValueList, 482 + /// [`FznsoValueMethods::len`], and elements in the list can be 483 + /// accessed using [`FznsoValueMethods::get_element`] 484 + FznsoValueList, 485 485 } 486 486 487 487 #[repr(C)] 488 488 #[derive(Clone, Debug)] 489 489 /// A struct containing the function pointers to interact with a 490 - /// [`IpdosValue`] 491 - pub struct IpdosValueMethods { 490 + /// [`FznsoValue`] 491 + pub struct FznsoValueMethods { 492 492 /// Function callback that returns the kind of the value. 493 - kind: extern "C" fn(&IpdosValue) -> IpdosValueKind, 493 + kind: extern "C" fn(&FznsoValue) -> FznsoValueKind, 494 494 /// Function callback that returns the length of the value. 495 495 /// 496 - /// In case [`IpdosValueMethods::kind`] returns 497 - /// [`IpdosValueKind::IpdosValueList`], the length is the number of elements 498 - /// in the list, accessible using [`IpdosValueMethods::get_element`]. 496 + /// In case [`FznsoValueMethods::kind`] returns 497 + /// [`FznsoValueKind::FznsoValueList`], the length is the number of elements 498 + /// in the list, accessible using [`FznsoValueMethods::get_element`]. 499 499 /// 500 - /// In case [`IpdosValueMethods::kind`] returns 501 - /// [`IpdosValueKind::IpdosValueSetInt`] or 502 - /// [`IpdosValueKind::IpdosValueSetFloat`], the length is the number of 500 + /// In case [`FznsoValueMethods::kind`] returns 501 + /// [`FznsoValueKind::FznsoValueSetInt`] or 502 + /// [`FznsoValueKind::FznsoValueSetFloat`], the length is the number of 503 503 /// ranges in the set, accessible using 504 - /// [`IpdosValueMethods::get_range_int`] or 505 - /// [`IpdosValueMethods::get_range_float`]. 504 + /// [`FznsoValueMethods::get_range_int`] or 505 + /// [`FznsoValueMethods::get_range_float`]. 506 506 /// 507 507 /// # Panics 508 508 /// 509 - /// This function callback may panic if [`IpdosValueMethods::kind`] does not 510 - /// return [`IpdosValueKind::IpdosValueList`], 511 - /// [`IpdosValueKind::IpdosValueSetInt`], or 512 - /// [`IpdosValueKind::IpdosValueSetFloat`]. 513 - len: extern "C" fn(&IpdosValue) -> usize, 509 + /// This function callback may panic if [`FznsoValueMethods::kind`] does not 510 + /// return [`FznsoValueKind::FznsoValueList`], 511 + /// [`FznsoValueKind::FznsoValueSetInt`], or 512 + /// [`FznsoValueKind::FznsoValueSetFloat`]. 513 + len: extern "C" fn(&FznsoValue) -> usize, 514 514 /// Function callback that returns the decision variable index contained in 515 515 /// the value. 516 516 /// 517 517 /// # Panics 518 518 /// 519 - /// This function callback may panic if [`IpdosValueMethods::kind`] does not 520 - /// return [`IpdosValueKind::IpdosValueDecision`]. 521 - get_decision: extern "C" fn(&IpdosValue) -> IpdosDecisionIdx, 519 + /// This function callback may panic if [`FznsoValueMethods::kind`] does not 520 + /// return [`FznsoValueKind::FznsoValueDecision`]. 521 + get_decision: extern "C" fn(&FznsoValue) -> FznsoDecisionIdx, 522 522 /// Function callback that returns the constraint index contained in the 523 523 /// value. 524 524 /// 525 525 /// # Panics 526 526 /// 527 - /// This function callback may panic if [`IpdosValueMethods::kind`] does not 528 - /// return [`IpdosValueKind::IpdosValueConstraint`]. 529 - get_constraint: extern "C" fn(&IpdosValue) -> IpdosConstraintIdx, 527 + /// This function callback may panic if [`FznsoValueMethods::kind`] does not 528 + /// return [`FznsoValueKind::FznsoValueConstraint`]. 529 + get_constraint: extern "C" fn(&FznsoValue) -> FznsoConstraintIdx, 530 530 /// Function callback that returns the integer value contained in the value. 531 531 /// 532 532 /// # Panics 533 533 /// 534 - /// This function callback may panic if [`IpdosValueMethods::kind`] does not 535 - /// return [`IpdosValueKind::IpdosValueInt`]. 536 - get_int: extern "C" fn(&IpdosValue) -> i64, 534 + /// This function callback may panic if [`FznsoValueMethods::kind`] does not 535 + /// return [`FznsoValueKind::FznsoValueInt`]. 536 + get_int: extern "C" fn(&FznsoValue) -> i64, 537 537 /// Function callback that returns the floating point value contained in the 538 538 /// value. 539 539 /// 540 540 /// # Panics 541 541 /// 542 - /// This function callback may panic if [`IpdosValueMethods::kind`] does not 543 - /// return [`IpdosValueKind::IpdosValueFloat`]. 544 - get_float: extern "C" fn(&IpdosValue) -> f64, 542 + /// This function callback may panic if [`FznsoValueMethods::kind`] does not 543 + /// return [`FznsoValueKind::FznsoValueFloat`]. 544 + get_float: extern "C" fn(&FznsoValue) -> f64, 545 545 /// Function callback that returns the string pointer value contained in the 546 546 /// value. 547 547 /// 548 548 /// # Panics 549 549 /// 550 - /// This function callback may panic if [`IpdosValueMethods::kind`] does not 551 - /// return [`IpdosValueKind::IpdosValueString`]. 552 - get_string: extern "C" fn(&IpdosValue) -> *const ffi::c_char, 550 + /// This function callback may panic if [`FznsoValueMethods::kind`] does not 551 + /// return [`FznsoValueKind::FznsoValueString`]. 552 + get_string: extern "C" fn(&FznsoValue) -> *const ffi::c_char, 553 553 /// Function callback that returns the Boolean value contained in the value. 554 554 /// 555 555 /// # Panics 556 556 /// 557 - /// This function callback may panic if [`IpdosValueMethods::kind`] does not 558 - /// return [`IpdosValueKind::IpdosValueBool`]. 559 - get_bool: extern "C" fn(&IpdosValue) -> bool, 557 + /// This function callback may panic if [`FznsoValueMethods::kind`] does not 558 + /// return [`FznsoValueKind::FznsoValueBool`]. 559 + get_bool: extern "C" fn(&FznsoValue) -> bool, 560 560 /// Function callback that returns a range from a range list representing 561 561 /// the integer set contained in the value. 562 562 /// 563 563 /// # Panics 564 564 /// 565 - /// This function callback may panic if [`IpdosValueMethods::kind`] does not 566 - /// return [`IpdosValueKind::IpdosValueSetInt`]. 567 - get_range_int: extern "C" fn(&IpdosValue, index: usize) -> [i64; 2], 565 + /// This function callback may panic if [`FznsoValueMethods::kind`] does not 566 + /// return [`FznsoValueKind::FznsoValueSetInt`]. 567 + get_range_int: extern "C" fn(&FznsoValue, index: usize) -> [i64; 2], 568 568 /// Function callback that returns a range from a range list representing 569 569 /// the floating point set contained in the value. 570 570 /// 571 571 /// # Panics 572 572 /// 573 - /// This function callback may panic if [`IpdosValueMethods::kind`] does not 574 - /// return [`IpdosValueKind::IpdosValueSetFloat`]. 575 - get_range_float: extern "C" fn(&IpdosValue, index: usize) -> [f64; 2], 573 + /// This function callback may panic if [`FznsoValueMethods::kind`] does not 574 + /// return [`FznsoValueKind::FznsoValueSetFloat`]. 575 + get_range_float: extern "C" fn(&FznsoValue, index: usize) -> [f64; 2], 576 576 /// Function callback that returns an element from the list contained in the 577 577 /// value. 578 578 /// 579 579 /// # Panics 580 580 /// 581 - /// This function callback may panic if [`IpdosValueMethods::kind`] does not 582 - /// return [`IpdosValueKind::IpdosValueList`]. 583 - get_element: extern "C" fn(&IpdosValue, index: usize) -> IpdosValueRef<'_>, 581 + /// This function callback may panic if [`FznsoValueMethods::kind`] does not 582 + /// return [`FznsoValueKind::FznsoValueList`]. 583 + get_element: extern "C" fn(&FznsoValue, index: usize) -> FznsoValueRef<'_>, 584 584 } 585 585 586 586 #[repr(C)] ··· 589 589 /// 590 590 /// The caller can use the `get_value` function to retrieve the value of the 591 591 /// used decision variables. 592 - pub struct IpdosValueRef<'a> { 592 + pub struct FznsoValueRef<'a> { 593 593 /// The data pointer to be the first argument of `get_value`. 594 - data: &'a IpdosValue, 594 + data: &'a FznsoValue, 595 595 /// Reference to the structure containing the function callbacks used to 596 596 /// interact with the value. 597 - methods: &'static IpdosValueMethods, 597 + methods: &'static FznsoValueMethods, 598 598 } 599 599 600 600 #[cfg(test)] 601 601 mod tests { 602 - use crate::{IpdosModelRef, IpdosSolutionRef, IpdosType, IpdosValueRef}; 602 + use crate::{FznsoModelRef, FznsoSolutionRef, FznsoType, FznsoValueRef}; 603 603 604 604 #[test] 605 605 fn memory() { 606 - assert_eq!(size_of::<IpdosModelRef>(), size_of::<u128>()); 607 - assert_eq!(size_of::<IpdosSolutionRef>(), size_of::<u128>()); 608 - assert_eq!(size_of::<IpdosType>(), size_of::<u64>()); 609 - assert_eq!(size_of::<IpdosValueRef>(), size_of::<u128>()); 606 + assert_eq!(size_of::<FznsoModelRef>(), size_of::<u128>()); 607 + assert_eq!(size_of::<FznsoSolutionRef>(), size_of::<u128>()); 608 + assert_eq!(size_of::<FznsoType>(), size_of::<u64>()); 609 + assert_eq!(size_of::<FznsoValueRef>(), size_of::<u128>()); 610 610 } 611 611 }
-412
rust/ipdos-types/src/rust_interaction.rs
··· 1 - use std::{ffi, mem}; 2 - 3 - use crate::{ 4 - IpdosConstraintIdx, IpdosDecisionIdx, IpdosValue, IpdosValueKind, IpdosValueMethods, 5 - IpdosValueRef, 6 - }; 7 - 8 - macro_rules! ipdos_value_impls { 9 - (vec $t:ty) => { 10 - impl<'a> From<&'a Vec<$t>> for IpdosValueRef<'a> { 11 - fn from(value: &'a Vec<$t>) -> Self { 12 - extern "C" fn kind(_: &IpdosValue) -> IpdosValueKind { 13 - IpdosValueKind::IpdosValueList 14 - } 15 - extern "C" fn len(val: &IpdosValue) -> usize { 16 - let val: &Vec<$t> = unsafe { mem::transmute(val) }; 17 - val.len() 18 - } 19 - extern "C" fn get_element<'a>(val: &'a IpdosValue, idx: usize) -> IpdosValueRef<'a> { 20 - let val: &Vec<$t> = unsafe { mem::transmute(val) }; 21 - IpdosValueRef::from(&val[idx]) 22 - } 23 - const IPDOS_LIST_VALUE_METHODS: &'static IpdosValueMethods = &IpdosValueMethods { 24 - kind, 25 - len, 26 - get_element, 27 - ..*IpdosValueRef::IPDOS_DEFAULT_VALUE_METHODS 28 - }; 29 - 30 - Self { 31 - data: unsafe { mem::transmute(value) }, 32 - methods: IPDOS_LIST_VALUE_METHODS, 33 - } 34 - } 35 - } 36 - 37 - impl TryFrom<&IpdosValueRef<'_>> for Vec<$t> { 38 - type Error = (); 39 - 40 - fn try_from(value: &IpdosValueRef<'_>) -> Result<Self, Self::Error> { 41 - if value.kind() != IpdosValueKind::IpdosValueList { 42 - return Err(()); 43 - } 44 - let len = value.len(); 45 - let mut result = Vec::with_capacity(len); 46 - for i in 0..len { 47 - result.push((&value.get_element(i)).try_into()?); 48 - } 49 - Ok(result) 50 - } 51 - } 52 - }; 53 - 54 - (opt $t:ty) => { 55 - impl From<&Option<$t>> for IpdosValueRef<'_> { 56 - fn from(value: &Option<$t>) -> Self { 57 - match value { 58 - Some(t) => IpdosValueRef::from(t), 59 - None => IpdosValueRef::from(&()), 60 - } 61 - } 62 - } 63 - 64 - impl TryFrom<&IpdosValueRef<'_>> for Option<$t> { 65 - type Error = (); 66 - 67 - fn try_from(value: &IpdosValueRef<'_>) -> Result<Self, Self::Error> { 68 - if value.kind() == IpdosValueKind::IpdosValueAbsent { 69 - Ok(None) 70 - } else { 71 - let val = value.try_into()?; 72 - Ok(Some(val)) 73 - } 74 - } 75 - } 76 - }; 77 - ($( $t:ty ),+) => { 78 - $( 79 - ipdos_value_impls!{vec $t} 80 - ipdos_value_impls!{opt $t} 81 - ipdos_value_impls!{vec Option<$t>} 82 - )+ 83 - }; 84 - } 85 - 86 - impl IpdosValueRef<'_> { 87 - const IPDOS_DEFAULT_VALUE_METHODS: &'static IpdosValueMethods = &IpdosValueMethods { 88 - kind: Self::absent_kind, 89 - len: Self::no_call, 90 - get_decision: Self::no_call, 91 - get_constraint: Self::no_call, 92 - get_int: Self::no_call, 93 - get_float: Self::no_call, 94 - get_string: Self::no_call, 95 - get_bool: Self::no_call, 96 - get_range_int: Self::no_call_idx, 97 - get_range_float: Self::no_call_idx, 98 - get_element: Self::no_call_idx, 99 - }; 100 - 101 - extern "C" fn absent_kind(_: &IpdosValue) -> IpdosValueKind { 102 - IpdosValueKind::IpdosValueAbsent 103 - } 104 - extern "C" fn no_call<T>(_: &IpdosValue) -> T { 105 - panic!("This value implementation does not provide this callback"); 106 - } 107 - extern "C" fn no_call_idx<T>(v: &IpdosValue, _: usize) -> T { 108 - Self::no_call(v) 109 - } 110 - 111 - /// Rust call to [`IpdosValueMethods::kind`] with the 112 - /// [`IpdosValueRef::data`] attribute. 113 - pub fn kind(&self) -> IpdosValueKind { 114 - (self.methods.kind)(self.data) 115 - } 116 - 117 - /// Rust call to [`IpdosValueMethods::len`] with the [`IpdosValueRef::data`] 118 - /// attribute. 119 - pub fn len(&self) -> usize { 120 - (self.methods.len)(self.data) 121 - } 122 - 123 - /// Rust call to [`IpdosValueMethods::get_decision`] with the 124 - /// [`IpdosValueRef::data`] attribute. 125 - pub fn get_decision(&self) -> IpdosDecisionIdx { 126 - (self.methods.get_decision)(self.data) 127 - } 128 - 129 - /// Rust call to [`IpdosValueMethods::get_constraint`] with the 130 - /// [`IpdosValueRef::data`] attribute. 131 - pub fn get_constraint(&self) -> IpdosConstraintIdx { 132 - (self.methods.get_constraint)(self.data) 133 - } 134 - 135 - /// Rust call to [`IpdosValueMethods::get_int`] with the 136 - /// [`IpdosValueRef::data`] attribute. 137 - pub fn get_int(&self) -> i64 { 138 - (self.methods.get_int)(self.data) 139 - } 140 - 141 - /// Rust call to [`IpdosValueMethods::get_float`] with the 142 - /// [`IpdosValueRef::data`] attribute. 143 - pub fn get_float(&self) -> f64 { 144 - (self.methods.get_float)(self.data) 145 - } 146 - 147 - /// Rust call to [`IpdosValueMethods::get_string`] with the 148 - /// [`IpdosValueRef::data`] attribute. 149 - pub fn get_string(&self) -> &'_ ffi::CStr { 150 - let s = (self.methods.get_string)(self.data); 151 - unsafe { ffi::CStr::from_ptr(s) } 152 - } 153 - 154 - /// Rust call to [`IpdosValueMethods::get_bool`] with the 155 - /// [`IpdosValueRef::data`] attribute. 156 - pub fn get_bool(&self) -> bool { 157 - (self.methods.get_bool)(self.data) 158 - } 159 - 160 - /// Rust call to [`IpdosValueMethods::get_range_int`] with the 161 - /// [`IpdosValueRef::data`] attribute. 162 - pub fn get_range_int(&self, idx: usize) -> (i64, i64) { 163 - let [min, max] = (self.methods.get_range_int)(self.data, idx); 164 - (min, max) 165 - } 166 - 167 - /// Rust call to [`IpdosValueMethods::get_range_float`] with the 168 - /// [`IpdosValueRef::data`] attribute. 169 - pub fn get_range_float(&self, idx: usize) -> (f64, f64) { 170 - let [min, max] = (self.methods.get_range_float)(self.data, idx); 171 - (min, max) 172 - } 173 - 174 - /// Rust call to [`IpdosValueMethods::get_element`] with the 175 - /// [`IpdosValueRef::data`] attribute. 176 - pub fn get_element(&self, idx: usize) -> IpdosValueRef<'_> { 177 - (self.methods.get_element)(self.data, idx) 178 - } 179 - } 180 - 181 - impl From<&()> for IpdosValueRef<'_> { 182 - fn from(value: &()) -> Self { 183 - Self { 184 - data: unsafe { mem::transmute(value) }, 185 - methods: Self::IPDOS_DEFAULT_VALUE_METHODS, 186 - } 187 - } 188 - } 189 - 190 - impl From<&bool> for IpdosValueRef<'_> { 191 - fn from(value: &bool) -> Self { 192 - extern "C" fn kind(_: &IpdosValue) -> IpdosValueKind { 193 - IpdosValueKind::IpdosValueBool 194 - } 195 - extern "C" fn get_bool(val: &IpdosValue) -> bool { 196 - let val: &bool = unsafe { mem::transmute(val) }; 197 - *val 198 - } 199 - const IPDOS_BOOL_VALUE_METHODS: &'static IpdosValueMethods = &IpdosValueMethods { 200 - kind, 201 - get_bool, 202 - ..*IpdosValueRef::IPDOS_DEFAULT_VALUE_METHODS 203 - }; 204 - 205 - Self { 206 - data: unsafe { mem::transmute(value) }, 207 - methods: IPDOS_BOOL_VALUE_METHODS, 208 - } 209 - } 210 - } 211 - 212 - impl From<&f64> for IpdosValueRef<'_> { 213 - fn from(value: &f64) -> Self { 214 - extern "C" fn kind(_: &IpdosValue) -> IpdosValueKind { 215 - IpdosValueKind::IpdosValueInt 216 - } 217 - extern "C" fn get_float(val: &IpdosValue) -> f64 { 218 - let val: &f64 = unsafe { mem::transmute(val) }; 219 - *val 220 - } 221 - const IPDOS_F64_VALUE_METHODS: &'static IpdosValueMethods = &IpdosValueMethods { 222 - kind, 223 - get_float, 224 - ..*IpdosValueRef::IPDOS_DEFAULT_VALUE_METHODS 225 - }; 226 - 227 - Self { 228 - data: unsafe { mem::transmute(value) }, 229 - methods: IPDOS_F64_VALUE_METHODS, 230 - } 231 - } 232 - } 233 - 234 - impl From<&i64> for IpdosValueRef<'_> { 235 - fn from(value: &i64) -> Self { 236 - extern "C" fn kind(_: &IpdosValue) -> IpdosValueKind { 237 - IpdosValueKind::IpdosValueInt 238 - } 239 - extern "C" fn get_int(val: &IpdosValue) -> i64 { 240 - let val: &i64 = unsafe { mem::transmute(val) }; 241 - *val 242 - } 243 - const IPDOS_I64_VALUE_METHODS: &'static IpdosValueMethods = &IpdosValueMethods { 244 - kind, 245 - get_int, 246 - ..*IpdosValueRef::IPDOS_DEFAULT_VALUE_METHODS 247 - }; 248 - 249 - Self { 250 - data: unsafe { mem::transmute(value) }, 251 - methods: IPDOS_I64_VALUE_METHODS, 252 - } 253 - } 254 - } 255 - 256 - impl From<&ffi::CStr> for IpdosValueRef<'_> { 257 - fn from(value: &ffi::CStr) -> Self { 258 - extern "C" fn kind(_: &IpdosValue) -> IpdosValueKind { 259 - IpdosValueKind::IpdosValueString 260 - } 261 - extern "C" fn get_string(val: &IpdosValue) -> *const ffi::c_char { 262 - let val: *const ffi::c_char = unsafe { mem::transmute(val) }; 263 - val 264 - } 265 - const IPDOS_STR_VALUE_METHODS: &'static IpdosValueMethods = &IpdosValueMethods { 266 - kind, 267 - get_string, 268 - ..*IpdosValueRef::IPDOS_DEFAULT_VALUE_METHODS 269 - }; 270 - 271 - Self { 272 - data: unsafe { mem::transmute(value.as_ptr()) }, 273 - methods: IPDOS_STR_VALUE_METHODS, 274 - } 275 - } 276 - } 277 - 278 - impl From<&ffi::CString> for IpdosValueRef<'_> { 279 - fn from(value: &ffi::CString) -> Self { 280 - value.as_c_str().into() 281 - } 282 - } 283 - 284 - impl From<&IpdosConstraintIdx> for IpdosValueRef<'_> { 285 - fn from(value: &IpdosConstraintIdx) -> Self { 286 - extern "C" fn kind(_: &IpdosValue) -> IpdosValueKind { 287 - IpdosValueKind::IpdosValueDecision 288 - } 289 - extern "C" fn get_constraint(val: &IpdosValue) -> IpdosConstraintIdx { 290 - let val: &IpdosConstraintIdx = unsafe { mem::transmute(val) }; 291 - *val 292 - } 293 - const IPDOS_CONSTRAINT_VALUE_METHODS: &'static IpdosValueMethods = &IpdosValueMethods { 294 - kind, 295 - get_constraint, 296 - ..*IpdosValueRef::IPDOS_DEFAULT_VALUE_METHODS 297 - }; 298 - 299 - Self { 300 - data: unsafe { mem::transmute(value) }, 301 - methods: IPDOS_CONSTRAINT_VALUE_METHODS, 302 - } 303 - } 304 - } 305 - 306 - impl From<&IpdosDecisionIdx> for IpdosValueRef<'_> { 307 - fn from(value: &IpdosDecisionIdx) -> Self { 308 - extern "C" fn kind(_: &IpdosValue) -> IpdosValueKind { 309 - IpdosValueKind::IpdosValueDecision 310 - } 311 - extern "C" fn get_decision(val: &IpdosValue) -> IpdosDecisionIdx { 312 - let val: &IpdosDecisionIdx = unsafe { mem::transmute(val) }; 313 - *val 314 - } 315 - const IPDOS_DECISION_VALUE_METHODS: &'static IpdosValueMethods = &IpdosValueMethods { 316 - kind, 317 - get_decision, 318 - ..*IpdosValueRef::IPDOS_DEFAULT_VALUE_METHODS 319 - }; 320 - 321 - Self { 322 - data: unsafe { mem::transmute(value) }, 323 - methods: IPDOS_DECISION_VALUE_METHODS, 324 - } 325 - } 326 - } 327 - 328 - impl TryFrom<&IpdosValueRef<'_>> for bool { 329 - type Error = (); 330 - 331 - fn try_from(value: &IpdosValueRef<'_>) -> Result<Self, Self::Error> { 332 - if (value.methods.kind)(value.data) == IpdosValueKind::IpdosValueBool { 333 - Ok((value.methods.get_bool)(value.data)) 334 - } else { 335 - Err(()) 336 - } 337 - } 338 - } 339 - 340 - impl TryFrom<&IpdosValueRef<'_>> for f64 { 341 - type Error = (); 342 - 343 - fn try_from(value: &IpdosValueRef<'_>) -> Result<Self, Self::Error> { 344 - if value.kind() == IpdosValueKind::IpdosValueFloat { 345 - Ok(value.get_float()) 346 - } else { 347 - Err(()) 348 - } 349 - } 350 - } 351 - 352 - impl TryFrom<&IpdosValueRef<'_>> for i64 { 353 - type Error = (); 354 - 355 - fn try_from(value: &IpdosValueRef<'_>) -> Result<Self, Self::Error> { 356 - if value.kind() == IpdosValueKind::IpdosValueInt { 357 - Ok(value.get_int()) 358 - } else { 359 - Err(()) 360 - } 361 - } 362 - } 363 - 364 - impl<'a> TryFrom<&'a IpdosValueRef<'a>> for &'a ffi::CStr { 365 - type Error = (); 366 - 367 - fn try_from(value: &'a IpdosValueRef<'a>) -> Result<Self, Self::Error> { 368 - if value.kind() == IpdosValueKind::IpdosValueString { 369 - Ok(value.get_string()) 370 - } else { 371 - Err(()) 372 - } 373 - } 374 - } 375 - 376 - impl TryFrom<&IpdosValueRef<'_>> for ffi::CString { 377 - type Error = (); 378 - 379 - fn try_from(value: &IpdosValueRef<'_>) -> Result<Self, Self::Error> { 380 - if value.kind() == IpdosValueKind::IpdosValueString { 381 - Ok(value.get_string().to_owned()) 382 - } else { 383 - Err(()) 384 - } 385 - } 386 - } 387 - 388 - impl TryFrom<&IpdosValueRef<'_>> for IpdosConstraintIdx { 389 - type Error = (); 390 - 391 - fn try_from(value: &IpdosValueRef<'_>) -> Result<Self, Self::Error> { 392 - if value.kind() == IpdosValueKind::IpdosValueConstraint { 393 - Ok(value.get_constraint()) 394 - } else { 395 - Err(()) 396 - } 397 - } 398 - } 399 - 400 - impl TryFrom<&IpdosValueRef<'_>> for IpdosDecisionIdx { 401 - type Error = (); 402 - 403 - fn try_from(value: &IpdosValueRef<'_>) -> Result<Self, Self::Error> { 404 - if value.kind() == IpdosValueKind::IpdosValueDecision { 405 - Ok(value.get_decision()) 406 - } else { 407 - Err(()) 408 - } 409 - } 410 - } 411 - 412 - ipdos_value_impls! { i64, f64, bool, IpdosConstraintIdx, IpdosDecisionIdx, ffi::CString }