Skip to content

Add a rule (constraint)

A rule is a function that looks at a candidate and returns pass/fail, the measured value, the allowed window and a sentence. The search enforces it; every report and the Studio explain it.

1. Write it

my_rules.py:

from meidnet.constraints import CONSTRAINTS

@CONSTRAINTS.register("no_lead", "Rejects any composition containing Pb.")
def no_lead(cand):
    return cand.result("no_lead", "Pb" not in cand.elements.values())

@CONSTRAINTS.register("mass_window", "Mean atomic mass must lie between min and max (g/mol).")
def mass_window(cand, min=0.0, max=200.0):
    from pymatgen.core import Element
    m = sum(Element(e).atomic_mass for e in cand.structure.species) / len(cand.structure)
    return cand.result("mass_window", min <= m <= max, float(m), (min, max), f"mean mass {m:.1f}")

What a candidate gives you: cand.elements ({group: element}), cand.structure (pymatgen, after symmetry refinement), cand.raw (before), cand.lattice_a, cand.predictions ({property: value}), cand.radius(group).

2. Register the file and name the rule

plugins: [my_rules.py]
generation:
  family: my_perovskite.yaml      # a copy of the built-in family with the rules appended:
constraints:
  - {name: charge_neutrality}
  - ...
  - {name: no_lead}
  - {name: mass_window, min: 0, max: 120}

3. Run

meidnet generate meidnet.yaml. The candidate cards list No lead and mass window with the measured value; the funnel shows how many compositions each removed.

A complete example lives in examples/custom_rules/ (a no toxic elements rule and a max cell edge rule), and notebook 03 does the same in Colab.

Soft terms

Rules decide acceptance. To steer the latent search instead (a penalty with a gradient), register a search term with @SEARCH_TERMS.register in meidnet.terms; it receives a SearchContext with the decoder's outputs. See rules and search terms.