Release notes#
The APIs before v3.0.0 are in beta and may change without prior notice.
v1.3#
v1.3.0 (2026-05-03)#
Breaking — TimeSlot paired-key data model:
The pre-v1.3.0 single-table TimeSlot encoding — where EDTSlot
and UCTSlot each carried per-(area, slot) load scaling and
per-(gen, slot) commitment as comma-separated string cells whose
list position implicitly aligned with Area.get_all_idxes() /
StaticGen.get_all_idxes() — has been replaced with explicit
paired keying.
Models renamed to drop the redundant "T":
EDTSlot→ams.models.timeslot.EDSlot,UCTSlot→ams.models.timeslot.UCSlot. Both are now slot-definition tables (idx,name,u).``EDSlot`` / ``UCSlot`` no longer carry ``sd`` or ``ug`` attributes. Code that accessed
ss.EDTSlot.sd.v/ss.EDTSlot.ug.v/ss.UCTSlot.sd.vdirectly will nowAttributeError. Read instead from the new per-axis tables below (or from the routine viartn.sd.v/rtn.ug.v, which now return 2D(narea, nslot)/(ngen, nslot)matrices).Three new per-axis tables hold the actual data:
EDSlotLoad(per-(area, slot)sd),EDSlotGen(per-(gen, slot)ug), andUCSlotLoad(per-(area, slot)sdfor UC).The
GCommitmodel stub (never wired up) was removed._data_check()now resolves everyRParam/Varmodelandimodelreference against the system at the start ofinit()and raisesValueError(with a difflib-suggested correction) on any unresolved reference. User-defined routine subclasses with a typo'dmodel='Bbus'-style reference that previously skated by as a silentrparam.owner is Nonenow hard-error during initialization.
A migration helper at tools/migrate_timeslot.py rewrites legacy
case files in place — both JSON and XLSX. Detection is by cell
content (comma-string ⇒ legacy); no version stamp needed. The nine
case files shipped in ams/cases/ have been migrated.
Migrating a custom case file:
python tools/migrate_timeslot.py path/to/case.json --in-place
New — ``RParam.horizon`` (2D pivot for input parameters):
RParam now accepts horizon= (an
RParam handle to the secondary axis) plus hindexer= (the
column on the row-owner model carrying the secondary key). When
both are set together with indexer / imodel, RParam.v
returns a 2D (primary.n, secondary.n) matrix pivoted from the
underlying long-format rows. Cells with no matching row default to
the source NumParam.default; duplicate (primary, secondary)
rows raise.
This mirrors the long-standing ams.opt.var.Var.horizon
convention used on the output side, so the input and output 2D
shapes share one pattern: primary indexer = model, secondary
indexer = horizon.
Behavior change — drops ``NumOp(np.transpose)`` workarounds:
The ED.ugt = NumOp(u=ug, fun=np.transpose, ...) shim is
retired — the RParam(model='EDSlotGen', horizon=…, hindexer=…)
shape returns (ngen, nslot) directly when materialized,
matching the e_str expectations. Likewise, the MPBase.sdT
shim was eliminated by flipping
ams.core.service.LoadScale.v() to consume sd as
(narea, nslot) and routing the SRBase / NSRBase reserve chain
through a small ams.utils.func.multiply_left_t() helper.
Note that this is a behavior change for any user code calling
ams.core.service.LoadScale directly with a custom sd
RParam: the expected input shape is now (narea, nslot), not
(nslot, narea). Likewise, EDSlot / UCSlot no longer
carry sd / ug columns — read from the new
EDSlotLoad.sd / EDSlotGen.ug / UCSlotLoad.sd tables.
New — per-call output path for ``System.report``:
ams.system.System.report() and the underlying
ams.report.Report.write() now accept a path keyword.
path may be a directory (the report file name is generated as
<case>_report.txt) or a full file path. An explicit path
overrides the system-level no_output flag — useful for one-off
inspection without flipping the global flag. Resolves
#186.
Default output path now honors ``system.files.output_path``:
When called with path=None,
export_csv(),
export_json(), and the
underlying ams.utils.paths.get_export_path() helper now write
to system.files.output_path (when set) instead of the current
working directory. This aligns export defaults with
report(), which already used
output_path. CWD remains the fallback when output_path is
empty (the FileMan default).
The change also reaches
ams.core.matprocessor.MParam.export_csv() /
export_npz() since they share
the same helper — mats.PTDF.export_csv() on a system loaded
with a non-empty output_path will now land there instead of
CWD.
New — ``RoutineBase.load_csv``:
Inverse of export_csv().
Reads a routine's CSV results back into the matching
Var / ExpressionCalc storage so users can inspect
prior solutions without rerunning the optimization. Single-period
and multi-period (EDSlot / UCSlot) shapes are both
supported.
Behavior change — ``load_json`` / ``load_csv`` mark converged:
A successful load_json() or
load_csv() now sets
self.converged = True and self.exit_code = 0 so subsequent
get() and
report() calls behave as if the routine
just solved. Previously, load_json left converged untouched.
If you previously relied on converged == False after loading
"candidate" results into a scratch system (for example, to gate a
later resolve), reset the flag explicitly after the load:
ss.DCOPF.load_json(path)
ss.DCOPF.converged = False # opt out of the new behavior
Documentation — service module selection guide:
ams.core.service now opens with a "service selection guide"
table mapping common needs to the right ROperationService
subclass, plus a documented .v caching contract on
RBaseService (subclasses recompute fresh
on each access; only ValueService returns
a stored value). Class definitions are regrouped by category
(generic ops → subset/aggregation → reduction/difference →
domain-specific → backward-compat aliases). No public API changes.
Deprecation — service classes with no production users:
NumExpandDim and
VarReduction now emit
DeprecationWarning on instantiation and will be removed in
v1.4.0. Both have zero call sites in ams.routines and
ams.core. Replacements:
NumExpandDim(u=..., axis=N)→NumOp(u=..., fun=np.expand_dims, expand_dims=N)(theexpand_dimskwarg already exists onNumOp).VarReduction(u=..., fun=np.ones)→ build the shape-only reduction matrix inline, e.g.np.ones((1, u.n)).
Internal — shared scalar-wrap helper:
NumOp and
NumOpDual v0 properties now share a
module-level _ensure_array helper rather than carrying
near-identical scalar-to-ndarray wrap blocks. Behavior unchanged.
v1.2#
v1.2.3 (2026-05-02)#
Migration — ``Constraint.is_eq`` retired:
The is_eq parameter on ams.opt.Constraint and
ams.routines.routine.RoutineBase.addConstrs() is removed.
Every Constraint e_str must now embed the relational
operator in the LHS-zero form: '<LHS> <= 0', '<LHS> == 0',
or '<LHS> >= 0'. The CVXPY canonicalization of every
inequality to lhs - rhs <= 0 (regardless of <= vs >=
direction) means Constraint.v keeps reporting slack-from-zero
uniformly.
Update any user routines or runtime customizations:
# Before
self.pglb = Constraint(name='pglb', e_str='-pg + pmine')
self.pb = Constraint(name='pb', e_str=pb, is_eq=True)
sp.RTED.addConstrs(name='cap', e_str='pg - pmax', is_eq=False)
# After
self.pglb = Constraint(name='pglb', e_str='-pg + pmine <= 0')
self.pb = Constraint(name='pb', e_str=pb + ' == 0')
sp.RTED.addConstrs(name='cap', e_str='pg - pmax <= 0')
A Constraint whose e_str (or e_fn body) does not
produce a cp.constraints.Constraint now raises TypeError
at evaluate time with a message naming the embedded-operator
forms expected. The codegen and eval-fallback paths share this
behavior.
See Migration: canonical CVXPY in e_str (v1.2.3) for the full rationale and worked examples.
Migration — ``e_str`` authoring contract:
Routine e_str strings (built-in routines and any user customization
via addConstrs / obj.e_str += '...') must now use the canonical
CVXPY namespace explicitly. The historical function-name rewrite layer
that translated mul(...), multiply(...), sum(...), and
a dot b into their cp.* / * equivalents has been removed.
Update any user customizations:
Old (now broken) |
New (canonical) |
Notes |
|---|---|---|
|
|
Element-wise multiply. |
|
|
Same. |
|
|
Reduction over a vector. |
|
|
Scalar-times-expression. Was already a thin alias. |
Routine symbol names (Var, RParam, Service, Expression,
Constraint) may no longer match a CVXPY atom name (e.g. sum,
multiply, vstack, power). The codegen path raises an
explanatory error if a collision is detected. This prevents a routine
from silently shadowing cp.X in the eval-fallback rewrite.
A small behavior change rides with the eval-fallback unification:
Constraint.e_str may now contain a relational operator
(pg <= pmax etc.). Previously Constraint.parse() appended
' == 0' / ' <= 0' unconditionally and an embedded operator
would have been a syntax-level "double op" at evaluate time. The
runtime now dispatches on whether the eval result is already a
cp.constraints.Constraint and skips the wrap when it is.
The SymProcessor.sub_map and SymProcessor.val_map
attributes are removed. Both fed the legacy regex-rewrite +
eval pipeline that the cvxpy-namespace passthrough has fully
replaced — symbol resolution now goes through
ams.opt._runtime_eval plus RoutineNS /
NumericRoutineNS. Anyone introspecting those dicts
should switch to formulation_source plus the routine's
vars / rparams / services / exprs / constrs
registries.
The ams.opt.OptzBase.formulation_source value
'sub_map' is renamed to 'eval'. The string referred to
the (now-deleted) SymProcessor.sub_map regex pipeline; the
new name reflects the live implementation —
ams.opt._runtime_eval.eval_e_str /
eval_e_str_numeric. Code that compared
item.formulation_source == 'sub_map' must update to
'eval'. The corresponding INFO log keys (formerly
sub_map(customized) / sub_map(added)) and
formulation_summary print bucket are renamed in lockstep.
Tightening the eval-fallback path:
ams.opt.Constraintnow validates at parse time thate_strends with the LHS-zero shape (<= 0/== 0/>= 0). Authoringpg <= pmaxinstead ofpg - pmax <= 0previously solved correctly but produced a silently-wrongOptzBase.e(numpy bool array instead of the LHS slack); the newams.opt._runtime_eval.assert_constraint_lhs_zero()guard surfaces the mismatch immediately with an actionable error.ams.opt._runtime_eval.eval_e_str()now logs a per-itemWARNINGwhen an eval-fallback constraint/objective/expression yields a non-DCP CVXPY object (e.g.cp.multiply(pg, pg)instead ofcp.square(pg)). The codegen path is unaffected; this closes the visibility gap on user customizations andaddConstrsadded by the cvxpy-namespace passthrough.ams.prep.generator.RESERVED_CVXPY_ATOM_NAMESis now derived at import time fromcvxpy.atoms(still a strict superset of the static fallback). New atoms in future CVXPY releases are guarded automatically.
Internal:
The
collect_dataandgroup_datahelpers inams.routines.routineare merged into a singleams.routines.routine.gather_results()with a keyword-onlygroupflag selecting the flat (CSV) vs nested (JSON) output shape. Closes issue #195.tests/reorganized into per-source-layer subfolders mirroringams/(tests/io/,tests/opt/,tests/routines/,tests/system/,tests/models/,tests/core/,tests/interop/,tests/cli/). Shared case fixtures (case5,case14,case_pjm5bus_demo, …) extracted totests/conftest.py; Family-A and Family-B–E routine scenarios consolidated into parametrized cross-checks; MATPOWER known-good comparisons parametrized. Newdocs/source/modeling/test_layout.rstdocuments the layout. Net: -3 600 lines duplicated boilerplate.
v1.2.2 (2026-05-01)#
New features:
Opt-layer codegen. Routine constraints, expressions, and objectives written as
e_strstrings are now compiled once to named Python callables in~/.ams/pycode/<routine>.py. The runtime path imports those callables instead of regex-rewritinge_strandeval-ing the result on every routine init.Author-facing API is unchanged — keep writing
e_str. The generated cache refreshes on first init when the routine sourcemd5changes; it can also be regenerated explicitly with the newams prepCLI:$ ams prep # generate for every routine $ ams prep --routine DCOPF # restrict to one $ ams prep --force # regenerate even when md5 matches $ ams prep --clean # wipe ~/.ams/pycode/ $ ams prep --where # print the cache path
See Routine for the rendered pipeline. Generated pycode is per-user and never shipped in the wheel — analogous to ANDES's
andes prep/~/.andes/pycode/pattern.Objective.add_term(fn)lets a mixin subclass extend a parent objective with an extra cost term via callable rather than the legacyself.obj.e_str += '...'string append. Used internally byESD1Base(charge/discharge cost) andRTEDVIS(virtual inertia/damping cost); available to user-defined mixins too.DPP-compliance diagnostic logged at
OModel.finalizetime. When a routine has parameters but the resultingcp.Problemis not DPP, an info-level log line warns that warm re-solves will re-canonicalize. Helps catch accidental non-DPP terms early.Formulation-source introspection. Three ways to see which execution path an opt element runs through after
init():per-item
ams.opt.OptzBase.formulation_source→'codegen' | 'sub_map' | 'manual' | 'pending';ams.routines.routine.RoutineBase.formulation_summary()prints a per-item table;an INFO log line on every
init():<DCOPF> formulation: codegen=14/17, sub_map(customized)=1, sub_map(added)=2
Useful for confirming a runtime customization (
addConstrs,obj.e_str += '...') actually reaches the optimizer rather than being silently overwritten by the cached callable.
Behavior changes:
Disk cache is always pristine. The generated pycode at
~/.ams/pycode/<routine>.pyis now guaranteed to reflect only the routine source code, never per-instance customizations. Codegen always runs against a freshams.Systeminstance fetched from a per-process singleton, never against the user'sself. Apristine = Truemarker in the generated module's header auto-invalidates caches written by older AMS versions on next read. This means runtime mutations on oneSystem(sp.DCOPF.obj.e_str += '...',sp.DCOPF.addConstrs(...)) cannot leak into another freshly-loadedSystem. Seeexamples/ex8.ipynbfor a working sp1 / sp2 / sp3 demonstration.e_stris preserved on items after auto-prep wires theire_fnfrom pycode. Lets users dosp.DCOPF.obj.e_str += '+ ...'post-init — a documented customization pattern that briefly broke when the_EFormDescriptormutex clearede_stron internal codegen wiring..e(the post-solve / debug numerical value of a constraint LHS, expression, or objective) now works correctly even when the solver bails or hasn't run yet. Resolves through a numeric proxy that returnsVar.v(zeros fallback) for unset variables — the same semantics the legacyval_map-eval path had.
Bug fixes:
bench.harness.measure: when warmup raises, the failure path now preserves the structured tags (routine,case,solver,phase,metadata) on the returnedMeasurementinstead of dropping them.LazyImport.__maybe_import_complementary_imports__narrows the swallowed exception from bareexcept Exceptiontoexcept ImportErrorand logs at DEBUG, so unexpected failures stop being silently hidden.
Internal:
Drop Codecov from CI in favor of Codacy as the single coverage provider. Removes
.codecov.yml, thecodecov/codecov-action+codecov/test-results-actionupload steps, the duplicate pytest run that producedjunit.xml, and the Codecov badge inREADME.md. Renames.github/workflows/codecov.ymltocoverage.ymlto match its now-Codacy-only role. TheCODECOV_TOKENrepository secret can be deleted.Silence Codacy's Bandit findings on the env-capture subprocess calls in
ams/bench/env.pyvia per-call# nosec B404/# nosec B603markers. Codacy's Bandit engine doesn't honor the[tool.bandit] skipsblock inpyproject.toml(it only passes a config file when the project's pattern set is empty), so the inline markers are what actually apply on Codacy. Localbandit -c pyproject.tomlruns continue to honor the skips list.ams.io.dump: initializeretdefensively before the format-dispatchif/elifto silence pylint'spossibly-used-before-assignment. The earlieroutput_formatsmembership guard already ensures one branch fires at runtime, soretwas never actually unbound — this is a static-analysis cleanup, not a behavior change.Add
encoding='utf-8'to text-modeopen()/Path.read_textcalls inams.bench.env,ams.bench.__main__, andams.system(config-file write). Avoids the platform-default encoding foot-gun on Windows.link_ext_param(model=None)andModel.set(..., base=None): document and explicitly drop the API-compat-only arguments so they no longer surface asunused-argumentlint findings.Bulk-disable noisy pylint patterns in
.prospector.yaml(too-many-arguments/-locals/-branches,use-list-literal/use-dict-literal,no-else-return,import-outside-toplevel,eval-used) with rationale; replaces per-PR Codacy churn on long-standing code.
v1.2.1 (2026-04-29)#
Bug fixes:
ams st(a.k.a.ams.main.selftest) now degrades gracefully on wheel installs. v1.2.0 correctly excluded thetests/directory from the built wheel, butams stwas still callingunittest.TestLoader().discover('<site-packages>/tests')and crashing withImportError: Start directory is not importable. The command now detects the missing directory, logs a one-line message pointing the user topytestfrom a clone, and exits cleanly. From a source clone the behavior is unchanged. While in the function, also harden the stdout-suppression block: save the caller's stdout (notsys.__stdout__) so wrappers likecontextlib.redirect_stdoutare preserved, restore + close the/dev/nullhandle in afinally, and gate the redirect onlogger.handlersbeing non-empty (replacing a try/except IndexError)
Improvements:
Add top-level
ams --versionflag that prints the AMS version (ams X.Y.Z), following the standard CLI convention used bypip,pytest,git, and others.ams misc --versionis unchanged and still prints the multi-line dependency block (Python, andes, numpy, cvxpy, solvers) for bug reportsRParam.v: pass scipy.sparse values through untouched on theis_extbranch (caller-suppliedv=...). PR #233 fixedMParam.vbut missed this parallel path; now the no-auto-densify contract is consistent acrossRParamandMParamNumOpDual.v0: pass scipy.sparse outputs through untouched whenarray_out=True, mirroring theNumOp.v0fix from PR #233. Previously sparse results were wrapped in a 1-element object-dtypendarray, which broke downstreamcsr_matrixconversion. Audit of all otherv0overrides (NumHstack,ZonalSum,VarSelect,VarReduction,RampSub) confirmed they all construct results via numpy ops that already returnndarray, so no parallel fix was needed thereMParam.vno longer auto-densifies sparse-stored matrices on every property access. The underlying scipy.sparse object is now returned as-is; a newMParam.dense()method materializes a densenumpy.ndarraywhen one is genuinely required..shapeand.nconsult the underlying value directly without densifying. Together with thesparse=Truedeclarations on the matrixRParamconsumers inDCPF/DCOPF/DCOPF2, this lets routines actually pass sparse matrices to CVXPY instead of silently densifying them on every parameter setMatProcessor.build_ptdf/build_lodfnow finalize the result ascsr_matrixrather than leaving it aslil_matrix.lilis the right format for incremental row assignment during construction but is poorly supported by downstream consumers (CVXPY, scipyCOOconversion); freezing tocsrat the end is the canonical patternNumOp.v0: pass scipy.sparse outputs through untouched whenarray_out=True. Previously sparse results were wrapped in a 1-elementnumpy.ndarrayof object dtype, which broke the subsequentcsr_matrixconversion inNumOp.v()for sparseNumOps such asDCOPF2.PTDFtMatProcessor.build_lodf: replace the densenp.ones+np.tilecolumn-broadcast inside the chunk loop with sparse column scaling that divides each column by(1 - h_chunk[j]), zeroing columns where the denominator is zero to preserve the priorsafe_divbehavior. Removes a transientnbranch × stepdense allocation that reached ~1 GB on ~70k-bus grids. Numerical output is unchanged.MatProcessor.build_cg: replace the O(ng²)list.indexlookup withStaticGen.idx2uidfor O(ng) total cost. Matters as generator counts grow; modest at current case sizes.MatProcessor.build_ptdf: factorize the reduced bus susceptance matrix once viascipy.sparse.linalg.splu()and reuse the factorization across all line chunks. Removes the dense full-Bbussolver path, which materialized annb × nbdense matrix and was unusable on grids beyond a few thousand buses. Large-case PTDF builds are noticeably faster (e.g. ~2.5× on a 2000-bus case in incremental mode); numerical output is unchanged. Theuse_umfpackkeyword is retained for backward compatibility but is now a no-op.
v1.2.0 (2026-04-23)#
Breaking changes:
Requires ANDES >= 2.0.0
Minimum Python version raised to 3.11 (supported: 3.11, 3.12, 3.13)
Installation now uses pyproject extras instead of
requirements*.txtfiles. Development install:pip install -e '.[dev,nlp]'; docs:pip install -e '.[doc]'(single quotes are required inzshbecause[...]is a glob pattern)In routine
e_strexpressions, multiplication must be explicit: use@for matrix-vector,mul()for element-wise, or*for scalar. The previous automaticword*word → @rewrite has been removed. See Routine for details
New:
Performance benchmark suite under
ams.bench. Runpython -m ams.benchto reproduce timings across standard cases and routines; baselines inbench/baselines/
Improvements:
import amsis faster and no longer instantiates an ANDESSystemat import timeCLI:
amswithout a subcommand now prints help cleanly; unknown commands produce a clear error instead of a tracebackLoading a case produces far fewer warnings (retired config keys are now silently purged instead of flagged on every startup)
Internal:
Build system migrated from
versioneertosetuptools-scm; this is the first release produced by the new pipeline
v1.0#
v1.1.1 (2025-12-23)#
Include objective function value in exported report
Add PTDF-based routines:
RTED2,RTED2DG,RTED2ESAdd routine
RTEDESPfor price run ofRTED2andRTED2ESRemove attribute info from class RoutineBase and all derived routines
Fix charging/discharging duration constraints in
RTEDESRefactor routine architecture to use cooperative multiple inheritance (MRO) for better component mixins
Refactor DCPF1.run and OPF.run
v1.1.0 (2025-12-18)#
Add parameter check to correct ESD1 associated GCost
Add ESD1 params: SOCend, cesdc, cesdd, tdc, tdd, tdc0, tdd0
Revise ESD1 related routines: RTEDES, EDES, and UCES
v1.0.16 (2025-09-28)#
Add GitHub action to automatically upload release to Zenodo
v1.0.15 (2025-09-28)#
Fix
DCOPF2.pbto use PTDF-based formulationAdd a demo to compare
DCOPF2andDCOPF, seeexamples/demonstration/demo_dcopf.ipynbIn DC type routines, set vBus value as 1 for placeholder
Include Summary and Objective value in exported JSON
v1.0.14 (2025-08-29)#
Add supported Python versions in README
v1.0.13 (2025-08-18)#
Add methods
export_npz,load_npz,load_csvinMatProcessorto save and load matrices from filesAdd methods
export_json,load_jsoninRoutineBaseto save and load routine results from JSON files
v1.0.12 (2025-05-29)#
Add RParam pd and qd in
DCPF1for easy access to loadBug fix in
RoutineBase.export_csvwhen path is specifiedFix bug in
io.matpower.system2mpcwith multiple PQ at one bus
v1.0.11 (2025-05-23)#
Refactor Documenter
Fix bug in documentation building
v1.0.10 (2025-05-23)#
Add bus type correction in
system.System.setupRevise
io.psse.readto complete model Zone when necessaryUse numerical Area and Zone idx in MATPOWER and PSSE RAW file conversion
Support JSON format addfile when converting to ANDES case
Add PSS/E v33 RAW file writer
In class
System, add wrapper methodsto_mpc,to_m,to_xlsx,to_json, andto_rawfor easier case file exportAdd wrapper routines for PYPOWER:
DCPF1,PFlow1,DCOPF1, andACOPF1In routine
DCOPFand its derivatives, add ExpressionCalcmu1mu2to calculate Lagrange multipliers of line flow limits constraintsAdd wrapper routine
OPFfor gurobi_optimodsAdd a demo to show newly added wrapper routines, see
examples/demonstration/demo_wrapper_routines.ipynbRevise
andes.common.config.Config.updateto ensure configuration parameters are consistently updated in both the object and its internal_dictRemove legacy revised PYPOWER module
Remove function
shared.ppc2df
v1.0.9 (2025-04-23)#
Improve MATPOWER file converter:
Add a M file case writer
Include Area and Zone in both MATPOWER read and write
v1.0.8 (2025-04-20)#
Run workflow "Publish" only on push tag event
Include Hawaii synthetic case from Hawaii Synthetic Grid
Remove matrices calculation functions in model
LineInclude
gentypeandgenfuelwhen parsing MATPOWER casesFix logging level in
ACOPF.run
v1.0.7 (2025-04-14)#
Address several wording issues in the documentation
Switch to
AreafromZonefor zonal calculationExtend common parameters in groups
StaticGenandStaticLoadwithareaSet case
pjm5bus_demo.xlsxas a all-inclusive caseInclude module
MatProcessorin the API documentationImprove Line parameters correction in
System.setupMake func
interface._to_andes_pflowpublicDiscard
sync_adsysstep in functo_andes_pflowto fix mistake in parameters conversionUpdate case files
v1.0.6 (2025-04-10)#
Enhance handling of Type 1 gencost: Automatically fallback to Type 2 gencost
Add parameter correction for zero line angle difference
v1.0.5 (2025-04-09)#
Include sensitivity matrices calculation demo in documentation
Add
DCOPF2, a PTDF-based DCOPF routineFix bug when update routine parameters before it is initialized
v1.0.4 (2025-04-05)#
Fix format in release notes
Add badges of GitHub relesase and commits in README
Add a demo to show sensitivity matrices calculation
v1.0.3 (2025-03-17)#
Bug fix in function
interface.parse_addfile, released in v1.0.3a1
v1.0.2 (2025-02-01)#
Enhance the GitHub Actions workflow file
Deprecate andes logger configuration in
config_loggerDeprecate solver specification in
demo_ESD1
v1.0.1 (2025-01-26)#
Hotfix: removed dependencies on SCIP and pyscipopt to resolve installation issues
v1.0.0 (2025-01-24)#
Breaking Change: rename model
RegiontoZonefor clarity. Prior case files without modification can run into error.Fix bugs in
RTED.dc2acMinor refacotr
OptzBase.get_idxto reduce duplicationRename module
OptBasetoOptzBasefor clarityUpdate benchamrk figure in README
Set ANDES requirement to v1.9.3
Deprecate method
get_idxand suggest usingget_all_idxesinsteadRemove module
benchmarks.pyand its tests for simplicity
Pre-v1.0#
v0.9.13 (2024-12-05)#
Add a step to report in
RoutineBase.runAdd more tests to cover DG and ES related routines
Improve formulation for DG and ESD involved routines
Improve module
Reportand methodRoutineBase.export_csvSupport
TimedEventin ANDES case conversionAdd Var
vBusinDCOPFfor placeholder
v0.9.12 (2024-11-23)#
Refactor
OModel.initializedas a property methodAdd a demo to show using
Constraint.efor debuggingFix
opt.omodel.Param.evaluatewhen its value is a numberImprove
opt.omodel.ExpressionCalcfor better performanceRefactor module
optAdd class
opt.ExpressionSwitch from PYPOWER to ANDES in routine
PFlowSwitch from PYPOWER to regular formulation in routine
DCPFRefactor routines
DCPFandDCOPFIn
RDocumenter, set Srouce to be owner if there is no srcSpecify
multiprocess<=0.70.16in requirements as 0.70.17 does not support Linux
RC1#
Reset setup.py to ensure compatibility
v0.9.11 (2024-11-14)#
Add pyproject.toml for PEP 517 and PEP 518 compliance
Add model
JumperFix deprecation warning related to
pandas.fillnaandnewshapein NumPyMinor refactor on solvers information in the module
sharedChange default values of minimum ON/OFF duration time of generators to be 1 and 0.5 hours
Add parameter
uffor enforced generator on/off statusIn servicee
LoadScale, consider load online statusConsider line online status in routine
EDAdd methods
evaluateandfinalizein the classOModelto handle optimization elements generation and assemblingRefactor
OModel.initandRoutine.initAdd ANDES paper as the citation file for now
Add more routine tests for generator trip, line trip, and load trip
Add a README to overview built-in cases
Rename methods
v2asefor classesConstraintandObjectiveAdd benchmark functions
Improve the usage of
evalin moduleomodelRefactor module
interop.andesas moduleinterfacefor simplicity
v0.9.10 (2024-09-03)#
Hotfix of import issue in v0.9.9.
In module
MatProcessor, add two parameterspermc_specanduse_umfpackin functionbuild_ptdfFollow RTD's deprecation of Sphinx context injection at build time
In MATPOWER conversion, set devices name as None
Skip macOS tests in azure-pipelines due to failure in fixing its configuration
Prepare to support NumPy v2.0.0, but solvers have unexpected behavior
Improve the logic of setting
OptzvalueSupport NumPy v2.0.0
v0.9.9 (2024-09-02)#
NOTICE: This version has known issues and has been yanked on PyPI.
v0.9.8 (2024-06-18)#
Assign
MParam.ownerwhen declaringIn
MatProcessor, improvebuild_ptdfandbuild_lodfto allow partial building and incremental buildingAdd file
cases/matpower/Benchmark.jsonfor benchmark with MATPOWERImprove known good results test
Minor fix in
main.pyselftest partSet dependency NumPy version to be <2.0.0 to avoid CVXPY compatibility issues
v0.9.7 (2024-05-24)#
This patch release add the Roadmap section in the release notes, to list out some potential features. It also drafts the EV Aggregation model based on the state space modelg, but the finish date remains unknown.
References:
[1] J. Wang et al., "Electric Vehicles Charging Time Constrained Deliverable Provision of Secondary Frequency Regulation," in IEEE Transactions on Smart Grid, doi: 10.1109/TSG.2024.3356948.
Fix OTDF calculation
Add parameter
dtype='float64'andno_store=FalseinMatProcessorPTDF, LODF, and OTDF calculation, to save memoryAdd placeholder parameter
Bus.type
v0.9.6 (2024-04-21)#
This patch release refactor and improve MatProcessor, where it support PTDF, LODF,
and OTDF for static analysis.
The reference can be found online "PowerWorld > Web Help > Sensitivities > Line Outage Distribution Factors".
Refactor DCPF, PFlow, and ACOPF
Add a loss factor in
RTED.dc2acAdd
DCOPF.dc2acFix OModel parse status to ensure no_parsed params can be updated
Fix and rerun
ex2Format
Routine.getreturn type to be consistent with input idx typeRemove unused
Routine.prepareRefactor
MatProcessorto separate matrix buildingAdd Var
plfinDCPF,PFlow, andACOPFto store the line flowAdd
build_ptdf,build_lodf, andbuild_otdfFix
Routine.getto support pd.Series type idx inputReserve
exec_timeafterdc2acAdjust kloss to fix
ex2
v0.9.5 (2024-03-25)#
Add more plots in
demo_AGCImprove line rating adjustment
Adjust static import sequence in
models.__init__.pyAdjust pjm5bus case line rate_a
Fix formulation of constraint line angle diff
Align slack bus angle to zero in
DCOPFAlign StaticGen idx sequence with converted MATPOWER case
Fix several issues in MATPOWER converter
v0.9.4 (2024-03-16)#
Add Var
piand ExpressionCalcpicto store the dual of constraint power balanceAdd Param
MandDto modelREGCV1Add CPS1 score calculation in
demo_AGC
v0.9.3 (2024-03-06)#
Major improvemets on
demo_AGCBug fix in
RTED.dc2ac
v0.9.2 (2024-03-04)#
Add
demo_AGCto demonstrate detailed secondary frequency regulation studyAdd
ExpressionCalcto handle post-solving calculationRename
type='eq'tois_eq=FalseinConstraintto avoid overriding built-in attributeSeveral formatting improvements
v0.9.1 (2024-03-02)#
Change sphinx extension myst_nb to nbsphinx for math rendering in
ex8Improve
symprocessorto include routine configAdd config to Routine reference
Fix symbol processor issue with power operator
v0.9.0 (2024-02-27)#
Add
ex8for formulation customization via APIImprove Development documentation
Fix
addService,addVarsRename
RoutineModeltoRoutineBasefor better namingFix ANDES file converter issue
Initial release on conda-forge
v0.8.5 (2024-01-31)#
Improve quality of coverage and format
Fix dependency issue
v0.8.4 (2024-01-30)#
Version cleanup
v0.8.3 (2024-01-30)#
Initial release on PyPI
v0.8.2 (2024-01-30)#
Improve examples
Add module
reportand funcRoutineBase.export_csvfor results export
v0.8.1 (2024-01-20)#
Improve
MatProcessorAdd more examples
Improve ANDES interface
v0.8.0 (2024-01-09)#
Refactor
DCEDroutines to improve performance
v0.7.5 (2023-12-28)#
Refactor
MatProcessorandDCEDroutines to improve performanceIntegrate sparsity pattern in
RParamRename energy storage routines
RTED2,ED2andUC2toRTEDES,EDESandUCES
v0.7.4 (2023-11-29)#
Refactor routins and optimization models to improve performance
Fix routines modeling
Add examples
Fix built-in cases
v0.7.3 (2023-11-03)#
Add tests
v0.7.2 (2023-10-26)#
Add routines
ED2andUC2Minor fix on
SymProcessorandDocumenter
v0.7.1 (2023-10-12)#
Add function
_initial_guessto routineUCRefactor PYPOWER
v0.7.0 (2023-09-22)#
Add interfaces for customizing optimization
Add models
REGCV1andREGCV1Costfor virtual inertia schedulingAdd cost models:
SRCost,NSRCost,DCostAdd reserve models:
SR,NSRAdd routine
UCAdd routine
RTED2to include energy storage model
v0.6.7 (2023-08-02)#
Version cleanup
v0.6.6 (2023-07-27)#
Improve routine reference
Add routine ED, LDOPF
v0.6.5 (2023-06-27)#
Update documentation with auto-generated model and routine reference
Add interface with ANDES
interop.andesAdd routine RTED and example of RTED-TDS co-simulation
Draft development documentation
v0.6.4 (2023-05-23)#
Setup PFlow and DCPF using PYPOWER
v0.6.3 (2023-05-22)#
Using CVXPY for draft implementation
Improve
model,group,paramandvarincoreRefactor
routinesandoptImprove PYPOWER interface
io.pypower.system2ppcFix PYPOWER function
solver.pypower.makePTDF
v0.6.2 (2023-04-23)#
Enhance docstring
Remove unused module
utils.LazyImportRemove unused module
shared
v0.6.1 (2023-03-05)#
Fix incompatiability of NumPy attribute
objectinio.matpower._get_bus_id_callerAdd file parser
io.pypowerfor PYPOWER case fileDeprecate PYPOWER interface
solvers.ipp
v0.6.0 (2023-03-04)#
Set up PYPOWER for power flow calculation
Add PYPOWER interface
solvers.ippDevelop module
routinesfor routine analysisRevise module
system,core.var,core.modelfor routine analysisSet up routine
PFlowfor power flow calculationAdd file parser
io.matpowerandio.rawfor MATPOWER file and RAW fileDocumentation of APIs
v0.5 (2023-02-17)#
Develop module
system,main,cliDevelopment preparation: versioneer, documentation, etc.
v0.4 (2023-01)#
This release outlines the package.