Skip to content

Variable Types

LunaModel supports four different variable types, each suited for different optimization scenarios.

Overview of Variable Types

Type Domain Use Case
BINARY {0, 1} Yes/no decisions, selection problems
INTEGER Whole numbers Counting, discrete quantities
SPIN {-1, +1} Ising models, quantum annealing
REAL Continuous Measurements, rates, percentages

Binary Variables

Binary variables represent boolean decisions: yes/no, true/false, selected/not selected.

Creating Binary Variables

Python
from luna_model import Model, Vtype

model = Model()
x = model.add_variable("x", vtype=Vtype.BINARY)

Common Use Cases

Selection problems:

Python
# Select items from a set
items = ['A', 'B', 'C', 'D']
selected = {item: model.add_variable(f"select_{item}", vtype=Vtype.BINARY)
            for item in items}

# Select exactly 2 items
model.add_constraint(sum(selected.values()) == 2)

Activation/deactivation:

Python
# Activate at most 3 features
features = [model.add_variable(f"feature_{i}", vtype=Vtype.BINARY) 
            for i in range(5)]
model.add_constraint(sum(features) <= 3)

Logical conditions:

Python
# If x then y
x = model.add_variable("x", vtype=Vtype.BINARY)
y = model.add_variable("y", vtype=Vtype.BINARY)
model.add_constraint(y <= x)  # y can only be 1 if x is 1

# x OR y (at least one must be true)
model.add_constraint(x + y >= 1)

# x XOR y (exactly one must be true)
model.add_constraint(x + y == 1)

Properties

  • Domain: {0, 1}
  • No need to specify bounds (implicit)
  • Most efficient for boolean decisions
  • Can be converted to/from SPIN variables

Integer Variables

Integer variables represent discrete quantities that can take whole number values.

Creating Integer Variables

Python
# Basic integer variable
x = model.add_variable("x", vtype=Vtype.INTEGER, lower=0, upper=100)

# Unbounded integer (not recommended)
y = model.add_variable("y", vtype=Vtype.INTEGER)

# Negative integers allowed
z = model.add_variable("z", vtype=Vtype.INTEGER, lower=-10, upper=10)

Common Use Cases

Counting:

Python
# Number of items to produce
num_items = model.add_variable("num_items", 
                               vtype=Vtype.INTEGER, 
                               lower=0, 
                               upper=1000)

# Number of workers to assign
num_workers = model.add_variable("num_workers",
                                 vtype=Vtype.INTEGER,
                                 lower=1,  # At least one worker
                                 upper=50)

Quantities:

Python
# Inventory levels
inventory = {}
for product in ['A', 'B', 'C']:
    inventory[product] = model.add_variable(
        f"inv_{product}",
        vtype=Vtype.INTEGER,
        lower=0,     # Non-negative
        upper=10000  # Warehouse capacity
    )

Discrete choices:

Python
# Select a priority level (1-5)
priority = model.add_variable("priority", vtype=Vtype.INTEGER, lower=1, upper=5)

# Time periods (0-23 for hours)
hour = model.add_variable("hour", vtype=Vtype.INTEGER, lower=0, upper=23)

Properties

  • Domain: Whole numbers (ℤ)
  • Always specify bounds (lb and ub) for better performance
  • More flexible than BINARY but slower to optimize
  • Can be converted to BINARY variables using transformations

Integer vs. Binary

When to use INTEGER vs. multiple BINARY variables:

Python
# Approach 1: Single integer (more compact)
quantity = model.add_variable("qty", vtype=Vtype.INTEGER, lower=0, upper=5)

# Approach 2: Multiple binaries (more constraints)
# Useful when you need to reference individual quantities
binary_vars = [model.add_variable(f"qty_{i}", vtype=Vtype.BINARY) 
               for i in range(6)]
quantity_value = sum(i * binary_vars[i] for i in range(6))
model.add_constraint(sum(binary_vars) == 1)  # Exactly one selected

Use INTEGER when: - The value itself is important - Range is large (>10) - Linear relationships suffice

Use multiple BINARYs when: - You need to reference specific values - Complex logical constraints apply - Targeting binary optimization solvers

Spin Variables

Spin variables are used in Ising models and quantum annealing applications.

Creating Spin Variables

Python
s = model.add_variable("s", vtype=Vtype.SPIN)

Common Use Cases

Ising models:

Python
# Create spin system
n = 5
spins = [model.add_variable(f"s_{i}", vtype=Vtype.SPIN) for i in range(n)]

# Ising objective: minimize energy
# H = -Σ J_ij * s_i * s_j - Σ h_i * s_i
J = [[0, 1, -1, 0, 0],
     [1, 0, 1, -1, 0],
     [-1, 1, 0, 1, -1],
     [0, -1, 1, 0, 1],
     [0, 0, -1, 1, 0]]

energy = 0
for i in range(n):
    for j in range(i+1, n):
        energy = energy - J[i][j] * spins[i] * spins[j]

model.objective = energy

Quantum annealing:

Python
# Spins for quantum annealer
qubits = [model.add_variable(f"q_{i}", vtype=Vtype.SPIN) 
          for i in range(10)]

# QUBO-style objective
objective = sum(qubits[i] * qubits[j] 
                for i in range(10) 
                for j in range(i+1, 10))
model.objective = objective

Properties

  • Domain: {-1, +1}
  • No bounds needed (implicit)
  • Natural for physics-inspired optimization
  • Can be converted to/from BINARY variables

Spin-Binary Conversion

Relationship between SPIN and BINARY:

Python
# Mathematical relationship:
# spin = 2 * binary - 1
# binary = (spin + 1) / 2

# Convert using transformation passes
from luna_model.transformation import PassManager
from luna_model.transformation.passes import BinarySpinPass

# Convert all to SPIN
pm = PassManager([BinarySpinPass(Vtype.SPIN, None)])
result = pm.run(model)
spin_model = result.model

# Convert all to BINARY
pm = PassManager([BinarySpinPass(Vtype.BINARY, None)])
result = pm.run(model)
binary_model = result.model

Real Variables

Real variables represent continuous quantities.

Creating Real Variables

Python
# Bounded real variable
x = model.add_variable("x", vtype=Vtype.REAL, lower=0.0, upper=1.0)

# Percentage
percentage = model.add_variable("pct", vtype=Vtype.REAL, lower=0.0, upper=100.0)

# Rate (can be negative)
growth_rate = model.add_variable("rate", vtype=Vtype.REAL, lower=-0.5, upper=0.5)

Common Use Cases

Continuous measurements:

Python
# Temperature, pressure, etc.
temperature = model.add_variable("temp", 
                                 vtype=Vtype.REAL, 
                                 lower=-20.0, 
                                 upper=120.0)

Fractions and ratios:

Python
# Allocation percentage (0-1)
allocation = model.add_variable("alloc", vtype=Vtype.REAL, lower=0.0, upper=1.0)

# Multiple allocations that sum to 1
n = 5
allocations = [model.add_variable(f"alloc_{i}", vtype=Vtype.REAL, lower=0.0) 
               for i in range(n)]
model.add_constraint(sum(allocations) == 1.0)

Relaxations:

Python
# LP relaxation of integer/binary problems
# (solve continuous version first, then round)
x_relaxed = model.add_variable("x_relax", vtype=Vtype.REAL, lower=0.0, upper=1.0)

Properties

  • Domain: Real numbers (ℝ)
  • Requires explicit bounds for most solvers
  • Most flexible but may need rounding for discrete problems
  • Generally faster to optimize than INTEGER

Mixed Variable Types

You can mix different variable types in the same model:

Python
model = Model()

# Binary decisions
is_active = model.add_variable("active", vtype=Vtype.BINARY)

# Integer quantities
quantity = model.add_variable("qty", vtype=Vtype.INTEGER, lower=0, upper=100)

# Real measurements
efficiency = model.add_variable("eff", vtype=Vtype.REAL, lower=0.0, upper=1.0)

# Constraints mixing types
model.add_constraint(quantity <= 100 * is_active)  # Big-M constraint
model.add_constraint(efficiency * quantity >= 50)   # Bilinear constraint

Type Conversions

LunaModel provides built-in transformations:

Binary ↔ Spin

Python
from luna_model.transformation import PassManager
from luna_model.transformation.passes import BinarySpinPass

model = Model()
x = model.add_variable("x", vtype=Vtype.BINARY)
s = model.add_variable("s", vtype=Vtype.SPIN)

# Convert everything to SPIN
pm = PassManager([BinarySpinPass(Vtype.SPIN, None)])
result = pm.run(model)

Integer → Binary

Python
# Transform integer to binary encoding
# (handled automatically by transformation passes)

Choosing the Right Type

Decision guide:

Question Answer Recommended Type
Is it a yes/no decision? Yes BINARY
Is it a discrete count or quantity? Small range (< 10) Consider BINARY
Is it a discrete count or quantity? Large range INTEGER
Is it for quantum annealing? Yes SPIN
Is it continuous or fractional? Yes REAL

Performance Considerations

Variable Type Speed Support Notes
BINARY ✅ Fastest ✅ Universal Best for boolean decisions, easy to interpret
INTEGER ⚠️ Slower ✅ Good More compact than multiple binaries, always set bounds
SPIN ⚠️ Varies ⚠️ Limited Natural for quantum annealing, requires conversion for classical solvers
REAL ✅ Fast ✅ Good Fastest to optimize, may need rounding for discrete problems

Examples by Domain

Logistics (BINARY + INTEGER)

Python
# Route selection (binary)
routes = [model.add_variable(f"route_{i}", vtype=Vtype.BINARY) 
          for i in range(10)]

# Package quantities (integer)
packages = model.add_variable("packages", vtype=Vtype.INTEGER, lower=0, upper=100)

Scheduling (BINARY + REAL)

Python
# Task assignment (binary)
assigned = model.add_variable("assigned", vtype=Vtype.BINARY)

# Task duration (real)
duration = model.add_variable("duration", vtype=Vtype.REAL, lower=0.0, upper=8.0)

Quantum Computing (SPIN)

Python
# All spin for quantum annealer
qubits = [model.add_variable(f"q_{i}", vtype=Vtype.SPIN) 
          for i in range(100)]

Financial Optimization (REAL)

Python
# Portfolio weights (real, sum to 1)
n_assets = 10
weights = [model.add_variable(f"w_{i}", vtype=Vtype.REAL, lower=0.0) 
           for i in range(n_assets)]
model.add_constraint(sum(weights) == 1.0)

Next Steps

  • Expressions - Build expressions with your variables
  • Constraints - Add constraints for different variable types