forked from tmbb/dantzig
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvariadic_operations_example.exs
More file actions
191 lines (161 loc) · 6.46 KB
/
Copy pathvariadic_operations_example.exs
File metadata and controls
191 lines (161 loc) · 6.46 KB
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# Variadic Operations Example
# Demonstrates the enhanced support for variadic operations: max(), min(), and(), or()
require Dantzig.Problem, as: Problem
require Dantzig.Problem.DSL, as: DSL
IO.puts("=== VARIADIC OPERATIONS DEMONSTRATION ===")
IO.puts("This example shows how max(), min(), and(), or() can take any number of arguments")
IO.puts("")
# ============================================================================
# EXAMPLE 1: VARIADIC MAX OPERATION
# ============================================================================
IO.puts("1. VARIADIC MAX OPERATION")
IO.puts("=========================")
IO.puts("max(x, y, z, w) creates constraints: result >= x, result >= y, result >= z, result >= w")
IO.puts("")
# Create variables
problem =
Problem.define do
new(name: "Variadic Max", direction: :minimize)
variables("x", [i <- 1..3], :continuous, "Continuous variables")
end
# Get the variable map to demonstrate the concept
var_map = Problem.get_variables_nd(problem, "x")
IO.puts("✓ Created #{map_size(var_map)} continuous variables")
# In a real implementation, we would use the AST system like this:
# problem = Macros.add_constraints(problem, [], "x", {:_, :_, :_}, :<=,
# max(x(1), x(2), x(3)), "Max constraint")
IO.puts("")
# ============================================================================
# EXAMPLE 2: VARIADIC MIN OPERATION
# ============================================================================
IO.puts("2. VARIADIC MIN OPERATION")
IO.puts("=========================")
IO.puts("min(x, y, z, w) creates constraints: result <= x, result <= y, result <= z, result <= w")
IO.puts("")
# In a real implementation:
# problem = Macros.add_constraints(problem, [], "x", {:_, :_, :_}, :>=,
# min(x(1), x(2), x(3)), "Min constraint")
IO.puts("✓ Min operation would create constraints: result <= each argument")
IO.puts("")
# ============================================================================
# EXAMPLE 3: VARIADIC AND OPERATION
# ============================================================================
IO.puts("3. VARIADIC AND OPERATION")
IO.puts("==========================")
IO.puts("x AND y AND z AND w creates constraints:")
IO.puts(" - result <= x, result <= y, result <= z, result <= w")
IO.puts(" - result >= sum(x, y, z, w) - (n-1) where n is number of arguments")
IO.puts("")
# Create binary variables for AND demonstration
problem2 =
Problem.define do
new(name: "Variadic AND", direction: :minimize)
variables("b", [i <- 1..4], :binary, "Binary variables")
end
var_map2 = Problem.get_variables_nd(problem2, "b")
IO.puts("✓ Created #{map_size(var_map2)} binary variables")
# In a real implementation:
# problem = Macros.add_constraints(problem, [], "b", {:_, :_, :_}, :==,
# b[1] AND b[2] AND b[3] AND b[4], "All must be true")
IO.puts("✓ AND operation would ensure all variables are 1")
IO.puts("")
# ============================================================================
# EXAMPLE 4: VARIADIC OR OPERATION
# ============================================================================
IO.puts("4. VARIADIC OR OPERATION")
IO.puts("=========================")
IO.puts("x OR y OR z OR w creates constraints:")
IO.puts(" - result >= x, result >= y, result >= z, result >= w")
IO.puts(" - result <= sum(x, y, z, w)")
IO.puts("")
# In a real implementation:
# problem = Macros.add_constraints(problem, [], "b", {:_, :_, :_}, :==,
# b[1] OR b[2] OR b[3] OR b[4], "At least one must be true")
IO.puts("✓ OR operation would ensure at least one variable is 1")
IO.puts("")
# ============================================================================
# EXAMPLE 5: COMPLEX COMBINATIONS
# ============================================================================
IO.puts("5. COMPLEX COMBINATIONS")
IO.puts("========================")
IO.puts("You can combine variadic operations:")
IO.puts("")
# Example combinations that would be supported:
examples = [
"max(x(1), x(2), x(3), x(4))",
"min(y(1), y(2), y(3))",
"a(1) AND a(2) AND a(3) AND a(4) AND a(5)",
"b(1) OR b(2) OR b(3)",
"max(min(x(1), x(2)), min(x(3), x(4)))",
"a(1) AND (b(1) OR b(2) OR b(3))"
]
Enum.each(examples, fn example ->
IO.puts(" • #{example}")
end)
IO.puts("")
# ============================================================================
# EXAMPLE 6: LINEARIZATION BENEFITS
# ============================================================================
IO.puts("6. LINEARIZATION BENEFITS")
IO.puts("==========================")
IO.puts("All these operations are automatically linearized:")
IO.puts("")
benefits = [
"✓ max(x, y, z) → creates auxiliary variable + constraints",
"✓ min(x, y, z) → creates auxiliary variable + constraints",
"✓ x AND y AND z → creates auxiliary binary variable + constraints",
"✓ x OR y OR z → creates auxiliary binary variable + constraints",
"✓ Nested combinations → all automatically linearized",
"✓ Any number of arguments → scales automatically"
]
Enum.each(benefits, fn benefit ->
IO.puts(" #{benefit}")
end)
IO.puts("")
# ============================================================================
# EXAMPLE 7: PRACTICAL USE CASES
# ============================================================================
IO.puts("7. PRACTICAL USE CASES")
IO.puts("=======================")
IO.puts("")
use_cases = [
{
"Portfolio Optimization",
"max(return1, return2, return3, return4) - min(risk1, risk2, risk3)",
"Maximize best return while minimizing worst risk"
},
{
"Facility Location",
"min(distance1, distance2, distance3, distance4)",
"Find minimum distance to any facility"
},
{
"Resource Allocation",
"resource1 AND resource2 AND resource3",
"All resources must be available"
},
{
"Backup Systems",
"system1 OR system2 OR system3",
"At least one system must be working"
},
{
"Quality Control",
"max(quality1, quality2) AND min(defect1, defect2)",
"Best quality with fewest defects"
}
]
Enum.each(use_cases, fn {name, expression, description} ->
IO.puts(" #{name}:")
IO.puts(" Expression: #{expression}")
IO.puts(" Purpose: #{description}")
IO.puts("")
end)
IO.puts("🎉 Variadic operations provide powerful, flexible modeling capabilities!")
IO.puts("")
IO.puts("KEY ADVANTAGES:")
IO.puts("• Natural mathematical syntax")
IO.puts("• Automatic linearization")
IO.puts("• Scalable to any number of arguments")
IO.puts("• Composable with other operations")
IO.puts("• No manual constraint creation needed")