solverforge 0.2.2__tar.gz → 0.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. {solverforge-0.2.2 → solverforge-0.2.4}/Cargo.lock +5 -5
  2. {solverforge-0.2.2 → solverforge-0.2.4}/Cargo.toml +1 -1
  3. {solverforge-0.2.2 → solverforge-0.2.4}/PKG-INFO +1 -1
  4. {solverforge-0.2.2 → solverforge-0.2.4}/pyproject.toml +1 -1
  5. {solverforge-0.2.2 → solverforge-0.2.4}/python/solverforge/__init__.py +66 -0
  6. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-python/python/solverforge/__init__.py +66 -0
  7. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-python/src/annotations.rs +174 -0
  8. solverforge-0.2.4/solverforge-python/src/lib.rs +171 -0
  9. solverforge-0.2.2/solverforge-python/src/lib.rs +0 -72
  10. {solverforge-0.2.2 → solverforge-0.2.4}/README.md +0 -0
  11. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/Cargo.toml +0 -0
  12. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/README.md +0 -0
  13. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/analysis/explanation.rs +0 -0
  14. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/analysis/manager.rs +0 -0
  15. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/analysis/mod.rs +0 -0
  16. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/bridge.rs +0 -0
  17. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/constraints/collectors.rs +0 -0
  18. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/constraints/constraint.rs +0 -0
  19. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/constraints/joiners.rs +0 -0
  20. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/constraints/mod.rs +0 -0
  21. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/constraints/stream.rs +0 -0
  22. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/domain/annotations.rs +0 -0
  23. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/domain/class.rs +0 -0
  24. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/domain/constraint_config.rs +0 -0
  25. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/domain/mod.rs +0 -0
  26. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/domain/model.rs +0 -0
  27. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/domain/shadow.rs +0 -0
  28. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/error.rs +0 -0
  29. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/handles.rs +0 -0
  30. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/lib.rs +0 -0
  31. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/score/bendable.rs +0 -0
  32. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/score/hard_soft.rs +0 -0
  33. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/score/hard_soft_decimal.rs +0 -0
  34. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/score/mod.rs +0 -0
  35. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/score/simple.rs +0 -0
  36. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/score/simple_decimal.rs +0 -0
  37. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/solver/builder.rs +0 -0
  38. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/solver/client.rs +0 -0
  39. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/solver/config.rs +0 -0
  40. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/solver/environment.rs +0 -0
  41. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/solver/factory.rs +0 -0
  42. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/solver/mod.rs +0 -0
  43. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/solver/request.rs +0 -0
  44. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/solver/response.rs +0 -0
  45. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/solver/termination.rs +0 -0
  46. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/traits.rs +0 -0
  47. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/value.rs +0 -0
  48. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/wasm/expr_builder.rs +0 -0
  49. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/wasm/expression.rs +0 -0
  50. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/wasm/generator.rs +0 -0
  51. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/wasm/host_functions.rs +0 -0
  52. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/wasm/memory.rs +0 -0
  53. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-core/src/wasm/mod.rs +0 -0
  54. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-python/Cargo.toml +0 -0
  55. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-python/README.md +0 -0
  56. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-python/src/bridge.rs +0 -0
  57. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-python/src/collectors.rs +0 -0
  58. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-python/src/decorators.rs +0 -0
  59. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-python/src/joiners.rs +0 -0
  60. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-python/src/lambda_analyzer.rs +0 -0
  61. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-python/src/score.rs +0 -0
  62. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-python/src/solver.rs +0 -0
  63. {solverforge-0.2.2 → solverforge-0.2.4}/solverforge-python/src/stream.rs +0 -0
@@ -1507,7 +1507,7 @@ dependencies = [
1507
1507
 
1508
1508
  [[package]]
1509
1509
  name = "solverforge"
1510
- version = "0.2.2"
1510
+ version = "0.2.4"
1511
1511
  dependencies = [
1512
1512
  "solverforge-core",
1513
1513
  "solverforge-derive",
@@ -1516,7 +1516,7 @@ dependencies = [
1516
1516
 
1517
1517
  [[package]]
1518
1518
  name = "solverforge-core"
1519
- version = "0.2.2"
1519
+ version = "0.2.4"
1520
1520
  dependencies = [
1521
1521
  "base64",
1522
1522
  "indexmap",
@@ -1532,7 +1532,7 @@ dependencies = [
1532
1532
 
1533
1533
  [[package]]
1534
1534
  name = "solverforge-derive"
1535
- version = "0.2.2"
1535
+ version = "0.2.4"
1536
1536
  dependencies = [
1537
1537
  "proc-macro2",
1538
1538
  "quote",
@@ -1544,7 +1544,7 @@ dependencies = [
1544
1544
 
1545
1545
  [[package]]
1546
1546
  name = "solverforge-python"
1547
- version = "0.2.2"
1547
+ version = "0.2.4"
1548
1548
  dependencies = [
1549
1549
  "log",
1550
1550
  "pyo3",
@@ -1557,7 +1557,7 @@ dependencies = [
1557
1557
 
1558
1558
  [[package]]
1559
1559
  name = "solverforge-service"
1560
- version = "0.2.2"
1560
+ version = "0.2.4"
1561
1561
  dependencies = [
1562
1562
  "base64",
1563
1563
  "chrono",
@@ -3,7 +3,7 @@ members = ["solverforge-core", "solverforge-python"]
3
3
  resolver = "2"
4
4
 
5
5
  [workspace.package]
6
- version = "0.2.2"
6
+ version = "0.2.4"
7
7
  edition = "2021"
8
8
  license = "Apache-2.0"
9
9
  repository = "https://github.com/solverforge/solverforge"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: solverforge
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: 3
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "solverforge"
7
- version = "0.2.2"
7
+ version = "0.2.4"
8
8
  description = "Python bindings for SolverForge constraint solver"
9
9
  readme = "README.md"
10
10
  license = { text = "Apache-2.0" }
@@ -24,6 +24,9 @@ from solverforge._solverforge import (
24
24
  PlanningEntityCollectionProperty,
25
25
  PlanningPin,
26
26
  InverseRelationShadowVariable,
27
+ PreviousElementShadowVariable,
28
+ NextElementShadowVariable,
29
+ CascadingUpdateShadowVariable,
27
30
  # Score types
28
31
  SimpleScore,
29
32
  HardSoftScore,
@@ -35,6 +38,36 @@ from solverforge._solverforge import (
35
38
  build_domain_model,
36
39
  DomainClass,
37
40
  DomainModel,
41
+ constraint_provider,
42
+ ConstraintProvider,
43
+ # Solver runtime
44
+ TerminationConfig,
45
+ DiminishedReturnsConfig,
46
+ EnvironmentMode,
47
+ MoveThreadCount,
48
+ SolverConfig,
49
+ SolveHandle,
50
+ SolveState,
51
+ ScoreDto,
52
+ SolveStatus,
53
+ SolveResponse,
54
+ SolverFactory,
55
+ Solver,
56
+ # Constraint streams
57
+ ConstraintFactory,
58
+ UniConstraintStream,
59
+ BiConstraintStream,
60
+ TriConstraintStream,
61
+ UniConstraintBuilder,
62
+ BiConstraintBuilder,
63
+ TriConstraintBuilder,
64
+ Constraint,
65
+ # Joiners
66
+ Joiner,
67
+ Joiners,
68
+ # Collectors
69
+ Collector,
70
+ ConstraintCollectors,
38
71
  )
39
72
 
40
73
  __all__ = [
@@ -51,6 +84,9 @@ __all__ = [
51
84
  "PlanningEntityCollectionProperty",
52
85
  "PlanningPin",
53
86
  "InverseRelationShadowVariable",
87
+ "PreviousElementShadowVariable",
88
+ "NextElementShadowVariable",
89
+ "CascadingUpdateShadowVariable",
54
90
  # Score types
55
91
  "SimpleScore",
56
92
  "HardSoftScore",
@@ -62,4 +98,34 @@ __all__ = [
62
98
  "build_domain_model",
63
99
  "DomainClass",
64
100
  "DomainModel",
101
+ "constraint_provider",
102
+ "ConstraintProvider",
103
+ # Solver runtime
104
+ "TerminationConfig",
105
+ "DiminishedReturnsConfig",
106
+ "EnvironmentMode",
107
+ "MoveThreadCount",
108
+ "SolverConfig",
109
+ "SolveHandle",
110
+ "SolveState",
111
+ "ScoreDto",
112
+ "SolveStatus",
113
+ "SolveResponse",
114
+ "SolverFactory",
115
+ "Solver",
116
+ # Constraint streams
117
+ "ConstraintFactory",
118
+ "UniConstraintStream",
119
+ "BiConstraintStream",
120
+ "TriConstraintStream",
121
+ "UniConstraintBuilder",
122
+ "BiConstraintBuilder",
123
+ "TriConstraintBuilder",
124
+ "Constraint",
125
+ # Joiners
126
+ "Joiner",
127
+ "Joiners",
128
+ # Collectors
129
+ "Collector",
130
+ "ConstraintCollectors",
65
131
  ]
@@ -24,6 +24,9 @@ from solverforge._solverforge import (
24
24
  PlanningEntityCollectionProperty,
25
25
  PlanningPin,
26
26
  InverseRelationShadowVariable,
27
+ PreviousElementShadowVariable,
28
+ NextElementShadowVariable,
29
+ CascadingUpdateShadowVariable,
27
30
  # Score types
28
31
  SimpleScore,
29
32
  HardSoftScore,
@@ -35,6 +38,36 @@ from solverforge._solverforge import (
35
38
  build_domain_model,
36
39
  DomainClass,
37
40
  DomainModel,
41
+ constraint_provider,
42
+ ConstraintProvider,
43
+ # Solver runtime
44
+ TerminationConfig,
45
+ DiminishedReturnsConfig,
46
+ EnvironmentMode,
47
+ MoveThreadCount,
48
+ SolverConfig,
49
+ SolveHandle,
50
+ SolveState,
51
+ ScoreDto,
52
+ SolveStatus,
53
+ SolveResponse,
54
+ SolverFactory,
55
+ Solver,
56
+ # Constraint streams
57
+ ConstraintFactory,
58
+ UniConstraintStream,
59
+ BiConstraintStream,
60
+ TriConstraintStream,
61
+ UniConstraintBuilder,
62
+ BiConstraintBuilder,
63
+ TriConstraintBuilder,
64
+ Constraint,
65
+ # Joiners
66
+ Joiner,
67
+ Joiners,
68
+ # Collectors
69
+ Collector,
70
+ ConstraintCollectors,
38
71
  )
39
72
 
40
73
  __all__ = [
@@ -51,6 +84,9 @@ __all__ = [
51
84
  "PlanningEntityCollectionProperty",
52
85
  "PlanningPin",
53
86
  "InverseRelationShadowVariable",
87
+ "PreviousElementShadowVariable",
88
+ "NextElementShadowVariable",
89
+ "CascadingUpdateShadowVariable",
54
90
  # Score types
55
91
  "SimpleScore",
56
92
  "HardSoftScore",
@@ -62,4 +98,34 @@ __all__ = [
62
98
  "build_domain_model",
63
99
  "DomainClass",
64
100
  "DomainModel",
101
+ "constraint_provider",
102
+ "ConstraintProvider",
103
+ # Solver runtime
104
+ "TerminationConfig",
105
+ "DiminishedReturnsConfig",
106
+ "EnvironmentMode",
107
+ "MoveThreadCount",
108
+ "SolverConfig",
109
+ "SolveHandle",
110
+ "SolveState",
111
+ "ScoreDto",
112
+ "SolveStatus",
113
+ "SolveResponse",
114
+ "SolverFactory",
115
+ "Solver",
116
+ # Constraint streams
117
+ "ConstraintFactory",
118
+ "UniConstraintStream",
119
+ "BiConstraintStream",
120
+ "TriConstraintStream",
121
+ "UniConstraintBuilder",
122
+ "BiConstraintBuilder",
123
+ "TriConstraintBuilder",
124
+ "Constraint",
125
+ # Joiners
126
+ "Joiner",
127
+ "Joiners",
128
+ # Collectors
129
+ "Collector",
130
+ "ConstraintCollectors",
65
131
  ]
@@ -383,6 +383,140 @@ impl PyInverseRelationShadowVariable {
383
383
  }
384
384
  }
385
385
 
386
+ /// Marks a field as a previous element shadow variable.
387
+ ///
388
+ /// Automatically tracks the previous element in a planning list variable.
389
+ /// Used with PlanningListVariable to access the element before this one.
390
+ ///
391
+ /// # Parameters
392
+ ///
393
+ /// - `source_variable_name`: Name of the planning list variable this shadows
394
+ ///
395
+ /// # Example
396
+ ///
397
+ /// ```python
398
+ /// @planning_entity
399
+ /// class Visit:
400
+ /// previous_visit: Annotated[Optional['Visit'], PreviousElementShadowVariable(source_variable_name='visits')]
401
+ /// ```
402
+ #[pyclass(name = "PreviousElementShadowVariable")]
403
+ #[derive(Clone, Debug)]
404
+ pub struct PyPreviousElementShadowVariable {
405
+ #[pyo3(get)]
406
+ pub source_variable_name: String,
407
+ }
408
+
409
+ #[pymethods]
410
+ impl PyPreviousElementShadowVariable {
411
+ #[new]
412
+ fn new(source_variable_name: String) -> Self {
413
+ Self {
414
+ source_variable_name,
415
+ }
416
+ }
417
+
418
+ fn __repr__(&self) -> String {
419
+ format!(
420
+ "PreviousElementShadowVariable(source_variable_name='{}')",
421
+ self.source_variable_name
422
+ )
423
+ }
424
+ }
425
+
426
+ /// Marks a field as a next element shadow variable.
427
+ ///
428
+ /// Automatically tracks the next element in a planning list variable.
429
+ /// Used with PlanningListVariable to access the element after this one.
430
+ ///
431
+ /// # Parameters
432
+ ///
433
+ /// - `source_variable_name`: Name of the planning list variable this shadows
434
+ ///
435
+ /// # Example
436
+ ///
437
+ /// ```python
438
+ /// @planning_entity
439
+ /// class Visit:
440
+ /// next_visit: Annotated[Optional['Visit'], NextElementShadowVariable(source_variable_name='visits')]
441
+ /// ```
442
+ #[pyclass(name = "NextElementShadowVariable")]
443
+ #[derive(Clone, Debug)]
444
+ pub struct PyNextElementShadowVariable {
445
+ #[pyo3(get)]
446
+ pub source_variable_name: String,
447
+ }
448
+
449
+ #[pymethods]
450
+ impl PyNextElementShadowVariable {
451
+ #[new]
452
+ fn new(source_variable_name: String) -> Self {
453
+ Self {
454
+ source_variable_name,
455
+ }
456
+ }
457
+
458
+ fn __repr__(&self) -> String {
459
+ format!(
460
+ "NextElementShadowVariable(source_variable_name='{}')",
461
+ self.source_variable_name
462
+ )
463
+ }
464
+ }
465
+
466
+ /// Marks a field as a cascading update shadow variable.
467
+ ///
468
+ /// A shadow variable that is updated based on other shadow variables or planning variables,
469
+ /// with updates cascading through a chain of elements.
470
+ ///
471
+ /// # Parameters
472
+ ///
473
+ /// - `target_method_name`: Name of the method to call for computing the shadow value
474
+ /// - `source_variable_name`: Optional name of the source variable that triggers updates
475
+ ///
476
+ /// # Example
477
+ ///
478
+ /// ```python
479
+ /// @planning_entity
480
+ /// class Visit:
481
+ /// arrival_time: Annotated[datetime, CascadingUpdateShadowVariable(
482
+ /// target_method_name='calculate_arrival_time',
483
+ /// source_variable_name='visits'
484
+ /// )]
485
+ /// ```
486
+ #[pyclass(name = "CascadingUpdateShadowVariable")]
487
+ #[derive(Clone, Debug)]
488
+ pub struct PyCascadingUpdateShadowVariable {
489
+ #[pyo3(get)]
490
+ pub target_method_name: String,
491
+ #[pyo3(get)]
492
+ pub source_variable_name: Option<String>,
493
+ }
494
+
495
+ #[pymethods]
496
+ impl PyCascadingUpdateShadowVariable {
497
+ #[new]
498
+ #[pyo3(signature = (target_method_name, source_variable_name=None))]
499
+ fn new(target_method_name: String, source_variable_name: Option<String>) -> Self {
500
+ Self {
501
+ target_method_name,
502
+ source_variable_name,
503
+ }
504
+ }
505
+
506
+ fn __repr__(&self) -> String {
507
+ match &self.source_variable_name {
508
+ Some(src) => format!(
509
+ "CascadingUpdateShadowVariable(target_method_name='{}', source_variable_name='{}')",
510
+ self.target_method_name, src
511
+ ),
512
+ None => format!(
513
+ "CascadingUpdateShadowVariable(target_method_name='{}')",
514
+ self.target_method_name
515
+ ),
516
+ }
517
+ }
518
+ }
519
+
386
520
  /// Marks a field as requiring deep planning cloning.
387
521
  ///
388
522
  /// Not needed for `planning_solution` or `planning_entity` attributes because those
@@ -454,6 +588,9 @@ pub fn register_annotations(m: &Bound<'_, PyModule>) -> PyResult<()> {
454
588
  m.add_class::<PyPlanningEntityCollectionProperty>()?;
455
589
  m.add_class::<PyPlanningPin>()?;
456
590
  m.add_class::<PyInverseRelationShadowVariable>()?;
591
+ m.add_class::<PyPreviousElementShadowVariable>()?;
592
+ m.add_class::<PyNextElementShadowVariable>()?;
593
+ m.add_class::<PyCascadingUpdateShadowVariable>()?;
457
594
  m.add_class::<PyDeepPlanningClone>()?;
458
595
  m.add_function(wrap_pyfunction!(py_deep_planning_clone, m)?)?;
459
596
  Ok(())
@@ -546,6 +683,43 @@ mod tests {
546
683
  assert!(shadow.__repr__().contains("visits"));
547
684
  }
548
685
 
686
+ #[test]
687
+ fn test_previous_element_shadow_variable() {
688
+ let shadow = PyPreviousElementShadowVariable::new("visits".to_string());
689
+ assert_eq!(shadow.source_variable_name, "visits");
690
+ assert!(shadow.__repr__().contains("visits"));
691
+ assert!(shadow.__repr__().contains("PreviousElementShadowVariable"));
692
+ }
693
+
694
+ #[test]
695
+ fn test_next_element_shadow_variable() {
696
+ let shadow = PyNextElementShadowVariable::new("visits".to_string());
697
+ assert_eq!(shadow.source_variable_name, "visits");
698
+ assert!(shadow.__repr__().contains("visits"));
699
+ assert!(shadow.__repr__().contains("NextElementShadowVariable"));
700
+ }
701
+
702
+ #[test]
703
+ fn test_cascading_update_shadow_variable() {
704
+ let shadow = PyCascadingUpdateShadowVariable::new(
705
+ "calculate_arrival".to_string(),
706
+ Some("visits".to_string()),
707
+ );
708
+ assert_eq!(shadow.target_method_name, "calculate_arrival");
709
+ assert_eq!(shadow.source_variable_name, Some("visits".to_string()));
710
+ assert!(shadow.__repr__().contains("calculate_arrival"));
711
+ assert!(shadow.__repr__().contains("visits"));
712
+ }
713
+
714
+ #[test]
715
+ fn test_cascading_update_shadow_variable_no_source() {
716
+ let shadow = PyCascadingUpdateShadowVariable::new("update_time".to_string(), None);
717
+ assert_eq!(shadow.target_method_name, "update_time");
718
+ assert_eq!(shadow.source_variable_name, None);
719
+ assert!(shadow.__repr__().contains("update_time"));
720
+ assert!(!shadow.__repr__().contains("source_variable_name"));
721
+ }
722
+
549
723
  #[test]
550
724
  fn test_deep_planning_clone() {
551
725
  let clone = PyDeepPlanningClone::new();
@@ -0,0 +1,171 @@
1
+ //! Python bindings for SolverForge constraint solver
2
+ //!
3
+ //! This crate provides Python bindings using PyO3, offering a 1:1 compatible API
4
+ //! with Timefold's Python bindings.
5
+
6
+ use pyo3::prelude::*;
7
+
8
+ mod annotations;
9
+ mod bridge;
10
+ mod collectors;
11
+ mod decorators;
12
+ mod joiners;
13
+ mod lambda_analyzer;
14
+ mod score;
15
+ mod solver;
16
+ mod stream;
17
+
18
+ pub use annotations::{
19
+ PyCascadingUpdateShadowVariable, PyDeepPlanningClone, PyInverseRelationShadowVariable,
20
+ PyNextElementShadowVariable, PyPlanningEntityCollectionProperty, PyPlanningEntityProperty,
21
+ PyPlanningId, PyPlanningListVariable, PyPlanningPin, PyPlanningScore, PyPlanningVariable,
22
+ PyPreviousElementShadowVariable, PyProblemFactCollectionProperty, PyProblemFactProperty,
23
+ PyValueRangeProvider,
24
+ };
25
+ pub use bridge::{PyBridge, PythonBridge};
26
+ pub use collectors::{PyCollector, PyConstraintCollectors};
27
+ pub use decorators::{PyConstraintProvider, PyDomainClass, PyDomainModel};
28
+ pub use joiners::{PyJoiner, PyJoiners};
29
+ pub use lambda_analyzer::{analyze_lambda, generate_lambda_name, LambdaInfo};
30
+ pub use score::{PyHardMediumSoftScore, PyHardSoftScore, PySimpleScore};
31
+ pub use solver::{
32
+ PyDiminishedReturnsConfig, PyEnvironmentMode, PyMoveThreadCount, PySolveHandle,
33
+ PySolveResponse, PySolveStatus, PySolver, PySolverConfig, PySolverFactory, PyTerminationConfig,
34
+ };
35
+ pub use stream::{
36
+ PyBiConstraintBuilder, PyBiConstraintStream, PyConstraint, PyConstraintFactory,
37
+ PyTriConstraintBuilder, PyTriConstraintStream, PyUniConstraintBuilder, PyUniConstraintStream,
38
+ };
39
+
40
+ /// SolverForge Python module
41
+ ///
42
+ /// Provides constraint solving capabilities with an API compatible with Timefold.
43
+ #[pymodule]
44
+ fn _solverforge(m: &Bound<'_, PyModule>) -> PyResult<()> {
45
+ // Version info
46
+ m.add("__version__", env!("CARGO_PKG_VERSION"))?;
47
+
48
+ // Bridge for Python-Rust object interop
49
+ m.add_class::<PyBridge>()?;
50
+
51
+ // Annotation marker classes
52
+ annotations::register_annotations(m)?;
53
+
54
+ // Score types
55
+ score::register_scores(m)?;
56
+
57
+ // Decorators
58
+ decorators::register_decorators(m)?;
59
+
60
+ // Constraint streams
61
+ stream::register_streams(m)?;
62
+
63
+ // Joiners
64
+ joiners::register_joiners(m)?;
65
+
66
+ // Collectors
67
+ collectors::register_collectors(m)?;
68
+
69
+ // Solver
70
+ solver::register_solver(m)?;
71
+
72
+ Ok(())
73
+ }
74
+
75
+ #[cfg(test)]
76
+ mod tests {
77
+ use super::*;
78
+
79
+ /// Verify that all solver runtime types are accessible from lib.rs exports
80
+ #[test]
81
+ fn test_solver_runtime_types_exported() {
82
+ // These type assertions verify the types are publicly re-exported
83
+ fn assert_type<T>() {}
84
+
85
+ assert_type::<PySolverConfig>();
86
+ assert_type::<PyTerminationConfig>();
87
+ assert_type::<PySolverFactory>();
88
+ assert_type::<PySolver>();
89
+ assert_type::<PySolveHandle>();
90
+ assert_type::<PySolveResponse>();
91
+ assert_type::<PySolveStatus>();
92
+ assert_type::<PyEnvironmentMode>();
93
+ assert_type::<PyMoveThreadCount>();
94
+ assert_type::<PyDiminishedReturnsConfig>();
95
+ }
96
+
97
+ /// Verify that all constraint stream types are accessible
98
+ #[test]
99
+ fn test_constraint_stream_types_exported() {
100
+ fn assert_type<T>() {}
101
+
102
+ assert_type::<PyConstraintFactory>();
103
+ assert_type::<PyUniConstraintStream>();
104
+ assert_type::<PyBiConstraintStream>();
105
+ assert_type::<PyTriConstraintStream>();
106
+ assert_type::<PyUniConstraintBuilder>();
107
+ assert_type::<PyBiConstraintBuilder>();
108
+ assert_type::<PyTriConstraintBuilder>();
109
+ assert_type::<PyConstraint>();
110
+ }
111
+
112
+ /// Verify that joiner types are accessible
113
+ #[test]
114
+ fn test_joiner_types_exported() {
115
+ fn assert_type<T>() {}
116
+
117
+ assert_type::<PyJoiner>();
118
+ assert_type::<PyJoiners>();
119
+ }
120
+
121
+ /// Verify that collector types are accessible
122
+ #[test]
123
+ fn test_collector_types_exported() {
124
+ fn assert_type<T>() {}
125
+
126
+ assert_type::<PyCollector>();
127
+ assert_type::<PyConstraintCollectors>();
128
+ }
129
+
130
+ /// Verify that decorator types are accessible
131
+ #[test]
132
+ fn test_decorator_types_exported() {
133
+ fn assert_type<T>() {}
134
+
135
+ assert_type::<PyConstraintProvider>();
136
+ assert_type::<PyDomainClass>();
137
+ assert_type::<PyDomainModel>();
138
+ }
139
+
140
+ /// Verify that score types are accessible
141
+ #[test]
142
+ fn test_score_types_exported() {
143
+ fn assert_type<T>() {}
144
+
145
+ assert_type::<PySimpleScore>();
146
+ assert_type::<PyHardSoftScore>();
147
+ assert_type::<PyHardMediumSoftScore>();
148
+ }
149
+
150
+ /// Verify that annotation types are accessible
151
+ #[test]
152
+ fn test_annotation_types_exported() {
153
+ fn assert_type<T>() {}
154
+
155
+ assert_type::<PyPlanningId>();
156
+ assert_type::<PyPlanningVariable>();
157
+ assert_type::<PyPlanningListVariable>();
158
+ assert_type::<PyPlanningScore>();
159
+ assert_type::<PyValueRangeProvider>();
160
+ assert_type::<PyProblemFactProperty>();
161
+ assert_type::<PyProblemFactCollectionProperty>();
162
+ assert_type::<PyPlanningEntityProperty>();
163
+ assert_type::<PyPlanningEntityCollectionProperty>();
164
+ assert_type::<PyPlanningPin>();
165
+ assert_type::<PyInverseRelationShadowVariable>();
166
+ assert_type::<PyPreviousElementShadowVariable>();
167
+ assert_type::<PyNextElementShadowVariable>();
168
+ assert_type::<PyCascadingUpdateShadowVariable>();
169
+ assert_type::<PyDeepPlanningClone>();
170
+ }
171
+ }
@@ -1,72 +0,0 @@
1
- //! Python bindings for SolverForge constraint solver
2
- //!
3
- //! This crate provides Python bindings using PyO3, offering a 1:1 compatible API
4
- //! with Timefold's Python bindings.
5
-
6
- use pyo3::prelude::*;
7
-
8
- mod annotations;
9
- mod bridge;
10
- mod collectors;
11
- mod decorators;
12
- mod joiners;
13
- mod lambda_analyzer;
14
- mod score;
15
- mod solver;
16
- mod stream;
17
-
18
- pub use annotations::{
19
- PyDeepPlanningClone, PyInverseRelationShadowVariable, PyPlanningEntityCollectionProperty,
20
- PyPlanningEntityProperty, PyPlanningId, PyPlanningListVariable, PyPlanningPin, PyPlanningScore,
21
- PyPlanningVariable, PyProblemFactCollectionProperty, PyProblemFactProperty,
22
- PyValueRangeProvider,
23
- };
24
- pub use bridge::{PyBridge, PythonBridge};
25
- pub use collectors::{PyCollector, PyConstraintCollectors};
26
- pub use decorators::{PyConstraintProvider, PyDomainClass, PyDomainModel};
27
- pub use joiners::{PyJoiner, PyJoiners};
28
- pub use lambda_analyzer::{analyze_lambda, generate_lambda_name, LambdaInfo};
29
- pub use score::{PyHardMediumSoftScore, PyHardSoftScore, PySimpleScore};
30
- pub use solver::{
31
- PyDiminishedReturnsConfig, PyEnvironmentMode, PyMoveThreadCount, PySolveHandle,
32
- PySolveResponse, PySolveStatus, PySolver, PySolverConfig, PySolverFactory, PyTerminationConfig,
33
- };
34
- pub use stream::{
35
- PyBiConstraintBuilder, PyBiConstraintStream, PyConstraint, PyConstraintFactory,
36
- PyTriConstraintBuilder, PyTriConstraintStream, PyUniConstraintBuilder, PyUniConstraintStream,
37
- };
38
-
39
- /// SolverForge Python module
40
- ///
41
- /// Provides constraint solving capabilities with an API compatible with Timefold.
42
- #[pymodule]
43
- fn _solverforge(m: &Bound<'_, PyModule>) -> PyResult<()> {
44
- // Version info
45
- m.add("__version__", env!("CARGO_PKG_VERSION"))?;
46
-
47
- // Bridge for Python-Rust object interop
48
- m.add_class::<PyBridge>()?;
49
-
50
- // Annotation marker classes
51
- annotations::register_annotations(m)?;
52
-
53
- // Score types
54
- score::register_scores(m)?;
55
-
56
- // Decorators
57
- decorators::register_decorators(m)?;
58
-
59
- // Constraint streams
60
- stream::register_streams(m)?;
61
-
62
- // Joiners
63
- joiners::register_joiners(m)?;
64
-
65
- // Collectors
66
- collectors::register_collectors(m)?;
67
-
68
- // Solver
69
- solver::register_solver(m)?;
70
-
71
- Ok(())
72
- }
File without changes