A constraint is a condition an optimization solution must satisfy. In linear programming, constraints are linear equations or inequalities that limit the decision variables. They turn budgets, available resources, and strategic requirements into a definition of which choices are feasible; the objective function then ranks those feasible choices. section 8.0 section 8.2
For feature selection, let xᵢ indicate whether feature i is selected: 1 means yes and 0 means no. A budget constraint adds the selected features’ costs and caps the total. In matrix form, A_ub x ≤ b_ub: each row of A_ub holds one constraint’s coefficients, and the corresponding entry of b_ub holds its limit. section 8.2 section 8.2.4
Different limits answer different planning questions:
- Budget: Keep first-year spending at or below $700,000 and total spending at or below $1.1 million. section 8.2.4
- Strategic balance: Select at least three and at most four features from each epic. section 8.1.3 section 8.2.4
- Resources: Check that the selection fits available workforce and time; these requirements need measurable limits before they can be encoded. section 8.1.2 section 8.2
Encoding budgets and minimum counts
With features in a fixed order, one row of A_ub contains their first-year costs and another contains their total costs; b_ub is [700000, 1100000]. For an epic, a row containing 1 for each of its features, paired with a limit of 4, sets the maximum. To express the minimum of 3 using the same ≤ form, use −1 for its features and a right-hand side of −3. Thus the model can apply both spending caps and selection-count limits before optimizing priority scores. section 8.2.2 section 8.2.4
>>> import numpy as np >>> A_ub = np.array([ >>> [f.cost_1yr for f in features], >>> [f.total_cost for f in features] >>> ]) >>> b_ub = np.array([700000, 1100000])
The NumPy arrays show how feature costs become two coefficient rows with matching budget limits. section 8.2.4
>>> epics = ['Enhance Data Infrastructure', >>> 'Improve Data Analytics and Reporting', >>> 'Advance Machine Learning and AI Capabilities'] >>> for epic in epics: >>> row_min = [-1 if f.epic == epic else 0 for f in features] >>> row_max = [1 if f.epic == epic else 0 for f in features] >>> A_ub = np.vstack([A_ub, row_min]) >>> A_ub = np.vstack([A_ub, row_max]) >>> b_ub = np.append(b_ub, -3) >>> b_ub = np.append(b_ub, 4)
The loop adds a lower and an upper selection-count inequality for each epic. section 8.2.4
After solving, check that a solution was found and inspect the selected features, costs, and priority scores. Changing limits also supports what-if comparisons, but the limits must still reflect the actual decision: an optimized choice is only practical if its constraints capture the relevant requirements. section 8.2.2 section 8.3


















