1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/// Creates an [`crate::AcyclicAssignments`] from assignment expressions.
///
/// This macro provides a convenient syntax for creating substitution assignments
/// using the syntax `assign! { var_id <- expression, ... }`. The macro validates
/// that the assignments are acyclic and returns an [`crate::AcyclicAssignments`] object.
///
/// # Syntax
///
/// ```text
/// assign! {
/// var_id1 <- expression1,
/// var_id2 <- expression2,
/// ...
/// }
/// ```
///
/// Where:
/// - `var_id` is a literal integer representing the variable ID
/// - `expression` is any expression that can be converted to a [`crate::Function`]
///
/// # Examples
///
/// Basic usage with linear expressions:
///
/// ```
/// use ommx::{assign, coeff, linear};
///
/// // Create assignments: x1 <- x2 + 1, x2 <- x3 + 2
/// let assignments = assign! {
/// 1 <- linear!(2) + coeff!(1.0),
/// 2 <- linear!(3) + coeff!(2.0)
/// };
/// ```
///
/// Using with more complex expressions:
///
/// ```
/// use ommx::{assign, coeff, linear};
///
/// // Create assignments with different expression types
/// let assignments = assign! {
/// 1 <- coeff!(5.0), // Constant assignment
/// 2 <- coeff!(2.0) * linear!(3) + coeff!(1.0), // Linear expression
/// 4 <- linear!(5) // Simple variable assignment
/// };
/// ```
///
/// # Panics
///
/// This macro panics if:
/// - The assignments contain cycles (e.g., x1 <- x2, x2 <- x1)
/// - A variable is assigned to an expression containing itself (e.g., x1 <- x1 + 1)
///
/// # Note
///
/// For runtime creation of assignments where error handling is needed,
/// use [`crate::AcyclicAssignments::new()`] directly:
///
/// ```
/// use ommx::{AcyclicAssignments, Function, VariableID, coeff, linear};
///
/// let assignments = vec![
/// (VariableID::from(1), Function::from(coeff!(5.0))),
/// (VariableID::from(2), Function::from(linear!(3) + coeff!(1.0))),
/// ];
///
/// match AcyclicAssignments::new(assignments) {
/// Ok(acyclic) => { /* use acyclic */ },
/// Err(err) => { /* handle error */ },
/// }
/// ```