Another way would be by introducing the new binary auxiliary variables $z_{i, j, a}$ and $w_a$ and imply the following constraints:
$$ z_{i,j,a} = 1 \iff\left(\sum_{b} x_{i,j,a,b} \geq 1\right) \quad \forall i,j,a \tag1$$
$$ w_a = 1 \iff\left(\sum_{u,v} y_{u,v,a} = 0\right) \quad \forall a \tag2$$
$$ z_{i,j,a} = 1 \implies w_a = 1 \quad \forall i,j,a \tag3$$
As far as I know, Pyomo has an internal facility to do these kinds of transformations somewhat automatically under a hood. The following snippet code can do this transformation:
model = pyo.ConcreteModel()
model.I = pyo.Set(initialize= range(2))
model.J = pyo.Set(initialize= range(2))
model.A = pyo.Set(initialize= range(2))
model.B = pyo.Set(initialize= range(2))
model.U = pyo.Set(initialize= range(2))
model.V = pyo.Set(initialize= range(2))
model.x = pyo.Var(model.I, model.J, model.A, model.B, domain= Binary, name= "x", bounds=(0, 1))
model.y = pyo.Var(model.I, model.J, model.A, domain= Binary, name= "y", bounds=(0, 1))
@model.Disjunction(model.I, model.J, model.A)
def rule(model, i, j ,a):
disjunct_A = [
sum(model.x[i,j,a,b] for b in model.B) == 1,
sum(model.y[u,v,a] for u in model.U for v in model.V) == 0
]
disjunct_B = [sum(model.x[i,j,a,b] for b in model.B) == 0,
sum(model.y[u,v,a] for u in model.U for v in model.V) >= 1
]
return [disjunct_A, disjunct_B]
@model.Objective(sense=pyo.maximize)
def obj(model):
return 0
pyo.TransformationFactory('gdp.bigm').apply_to(model)