Faebryk parameter solver'ın nasıl çalıştığını (Sets/Literals, Parameters, Expressions), mutation sırasında uygulanan temel invariantları ve solver'ı debug etme ile genişletme için pratik workflow'ları açıklar. Constraint solving, parameter bounds veya expression simplification debug etme işlemleri sırasında kullanın.
cd ~/.claude/skills
git clone https://github.com/atopile/atopile.git atopile mkdir -p ~/.claude/skills/solver
curl -fsSL https://raw.githubusercontent.com/atopile/atopile/HEAD/.claude/skills/solver/SKILL.md \
-o ~/.claude/skills/solver/SKILL.md Solver, atopile'nin parametre alt sisteminin kalbidir: Parametreler, Literaller (Kümeler) ve İfadelerden oluşturulan kısıt sistemlerini sembolik olarak basitleştirir ve kontrol eder.
Solver'ın iç yapısını değiştiriyorsanız, önce bunları okuyun:
src/faebryk/core/solver/README.md (konseptler, küme korelasyonu, sadece-append grafleri, canonicalization)src/faebryk/core/solver/symbolic/invariants.py (ifade ekleme sırasında uygulanan gerçek değişmezler)import faebryk.core.node as fabll
import faebryk.library._F as F
from faebryk.core.solver.defaultsolver import DefaultSolver
from faebryk.libs.test.boundexpressions import BoundExpressions
E = BoundExpressions()
class _App(fabll.Node):
x = F.Parameters.NumericParameter.MakeChild(unit=E.U.dl)
app = _App.bind_typegraph(tg=E.tg).create_instance(g=E.g)
x = app.x.get().can_be_operand.get()
E.is_subset(x, E.lit_op_range(((9, E.U.dl), (11, E.U.dl))), assert_=True)
solver = DefaultSolver()
res = solver.simplify(g=E.g, tg=E.tg, terminal=True).data.mutation_map
lit = res.try_extract_superset(app.x.get().is_parameter_operatable.get(), domain_default=True)
assert lit is not None
src/faebryk/core/solver/defaultsolver.py (DefaultSolver, iterasyon döngüsü, terminal vs non-terminal)src/faebryk/core/solver/solver.py (solver protokolü + yardımcı API'ler)src/faebryk/core/solver/mutator.py (Mutator, Transformations, MutationStage, MutationMap, tracebacks)src/faebryk/core/solver/symbolic/invariants.py (insert_expression(...) değişmez pipeline'ı)src/faebryk/core/solver/symbolic/canonical.py (canonicalization geçişleri)src/faebryk/core/solver/symbolic/* (yapısal + ifade-yönlü algoritmalar)src/faebryk/library/Parameters.py (ParameterOperatables, domainler, kompakt repr)src/faebryk/library/Expressions.py (ifade düğüm türleri, yüklemler, assertables)src/faebryk/library/Literals.py (Kümeler; sayısal/boolean/enum literalleri)src/faebryk/libs/test/boundexpressions.py (testler için kısa graf + ifade oluşturma)src/faebryk/library/): parametreleri/kısıtlamaları tanımlar (ör. R.resistance)ato kısıtlamalarını solver ifadelerine çevirir100kOhm +/- 10% gibi bir literal bir Küme (aralık), skaler değil.X - X X bir aralık olduğunda mutlaka {0} değildir, ama X bir tekil küme olduğunda mutlaka {0} olur.Parameter matematiksel bir sembol (değişken) gibi davranır, Python değişkeni değil.Is(A, B).assert_() / A.alias_is(B) güçlü "bunlar aynı" korelasyonu oluşturur.IsSubset(A, X).assert_() / A.constrain_subset(X) A'yı X içinde olacak şekilde kısıtlar.IsSubset(X, A).assert_() / A.constrain_superset(X) A'yı en azından X kabul edecek şekilde kısıtlar.İfadeler, operand düğümlerine işaret eden Faebryk grafındaki düğümlerdir. Bu önemlidir çünkü…
Solver bir ifadeyi yerinde "düzenleyemez". Bunun yerine:
MutationMap),BoundExpressions tercih edin).DefaultSolver().simplify(...) çalıştırın ve ortaya çıkan MutationMap'i inceleyin.src/faebryk/core/solver/symbolic/invariants.py::insert_expression içindeki değişmez pipeline'ını anladığınızdan ve koruduğunuzdan emin olun.src/faebryk/core/solver/symbolic/* içinde algoritmalar ekleyin/ayarlayın (çoğu mantık orada yaşar, mutator.py içinde değil).test/core/solver/ içinde yaşar:
test/core/solver/test_solver.pytest/core/solver/test_literal_folding.pytest/core/solver/test_solver_util.pyTekrar ederken sıkı bir döngü çalıştırın:
ato dev test --llm test/core/solver -k invariant -qato dev test --llm test/core/solver/test_solver.py::test_simplify -qsimplify(...) argümanlarını tercih edinDefaultSolver.simplify (tg, g) veya (g, tg) kabul eden bir uyumluluk katmanına sahiptir. Yeni kodda adlandırılmış argümanları tercih edin:
res = DefaultSolver().simplify(g=g, tg=tg, terminal=True)
mutation_map = res.data.mutation_map
Mutator/insert_expression pipeline'ını kullanınBir ifadeyi "oluşturduğunuzda" veya "yeniden yazdığınızda", gerçekten solver'dan geçici grafa bir şey eklemesini istiyorsunuz değişmezleri uphold ederken. Bunun gerçekleştiği kanonik yer:
src/faebryk/core/solver/symbolic/invariants.py::insert_expressionBunu bypass ederseniz, neredeyse kesinlikle bir değişmezi ihlal edeceksiniz ve şunu alacaksınız:
insert_expression)Değişmez pipeline'ı sıra-hassastır. Yüksek seviyede uyguladığı şey (parafraze):
Op(P!, ...) mümkün olduğunca boolean literalleri kullanmak üzere yeniden yazılırP{S|True} -> P!; P!{S/P|False} -> Contradiction; P!{S|True} -> P!f(A{S|{x}}, ...) -> f(x, ...)Yeni bir algoritma eklerken, doğru kalmak için en kolay yol yeni bir ExpressionBuilder oluşturmak
ve insert_expression'ın zor işi yapmasına izin vermektir.
DefaultSolver() durum tutar: terminal=False ile çağrıldığında, artımlı çözme için yeniden kullanılabilir iç durumu tutabilir.terminal=True (varsayılan) daha güçlüdür ama artımlı durum olarak yeniden kullanılması amaçlanmamıştır.terminal=False sadece non-terminal algoritmaları çalıştırır ve sonraki çağrılar için reusable_state depolar.simplify(..., relevant=[...]) "tüm dünyayı çözme"yi kaçınmak için amaçlanan kancadır.MutationStage: bir algoritma uygulaması giriş graf → çıkış graf, Transformations nesnesiyle.MutationMap: aşamaların bir zinciri; şunu yapmanızı sağlar:
map_forward)map_backward)try_extract_superset; subset çıkarma tipik olarak eşlenmiş operable'ın try_extract_subset() aracılığıyla yapılır)mutator.py içinde Traceback)Faydalı konfigürasyon bayrakları (bkz. src/faebryk/core/solver/utils.py):
SLOG=1: solver/mutator için hata ayıklama loggingSPRINT_START=1: her fazın başlangıcını log edinSVERBOSE_TABLE=1: ayrıntılı mutasyon tablolarıSSHOW_SS_IS=1: graf yazdırma çıktılarında subset/is yüklemlerini içeyinSMAX_ITERATIONS=N: kötü yeniden yazmaları yakalarken erken ise yükselt (sonsuz döngüyü bulunmasına yardımcı olur)Hatalarda, Contradiction / ContradictionByLiteral çıktısını arayın: mutasyon tracebacks'ini
orijin ifadelerine/parametrelerine geri yazdırır, bu genellikle gerçek hataya en kısa yoldur.
relevant=[...] aracılığıyla kapsamı kısıtlamayı tercih edin.2 veya daha fazla bağımsız görevin paralel olarak yürütülebileceği ve aralarında state paylaşımı ya da sıralı bağımlılık olmadığı durumlarda kullanın.
Ayrı bir oturumda inceleme kontrol noktaları ile yürütülecek yazılı bir uygulama planınız olduğunda kullanın.
Mevcut oturumda bağımsız görevlerle uygulama planlarını yürütürken kullanın
Herhangi bir hata, test başarısızlığı veya beklenmeyen davranışla karşılaştığınızda, çözüm önerisi sunmadan önce kullanın.
Herhangi bir feature ya da bugfix uygulamaya başlamadan önce kullanın.
Yeni beceriler oluştururken, mevcut becerileri düzenlerken veya dağıtımdan önce becerileri doğrularken kullanın.