Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to [`SecondQuantizedAlgebra.jl`](https://github.com/qojulia/
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v0.6.4]

### Fixed

- `change_index` now correctly zeros `DoubleIndexedVariable` nodes tagged `identical=false` even when they appear nested inside a larger product or sum. Previously `_check_not_identical` only examined the root of the substituted expression, so a `J(i,j)` factor inside `J(i,j) * x` would survive a `j → i` substitution intact instead of collapsing to zero. The fix walks the full expression tree, collects every `NotIdentical`-tagged node whose two index arguments became equal, and replaces them all via a single `Symbolics.substitute` pass.

## [v0.6.3]

### Changed
Expand Down Expand Up @@ -160,4 +166,5 @@ These names keep their meaning across the migration. Code that only uses them sh
[v0.6.1]: https://github.com/qojulia/SecondQuantizedAlgebra.jl/releases/tag/v0.6.1
[v0.6.2]: https://github.com/qojulia/SecondQuantizedAlgebra.jl/releases/tag/v0.6.2
[v0.6.3]: https://github.com/qojulia/SecondQuantizedAlgebra.jl/releases/tag/v0.6.3
[v0.6.4]: https://github.com/qojulia/SecondQuantizedAlgebra.jl/releases/tag/v0.6.4
[#156]: https://github.com/qojulia/SecondQuantizedAlgebra.jl/issues/156
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "SecondQuantizedAlgebra"
uuid = "f7aa4685-e143-4cb6-a7f3-073579757907"
version = "0.6.3"
version = "0.6.4"

[deps]
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
Expand Down
32 changes: 24 additions & 8 deletions src/expressions/index.jl
Original file line number Diff line number Diff line change
Expand Up @@ -256,18 +256,34 @@ function create_index_arrays(indices::Vector{Index}, ranges::Vector{<:AbstractRa
return vec(collect(Iterators.product(ranges...)))
end

"""Check if a substituted BasicSymbolic node with NotIdentical metadata has equal args → 0."""
"""
Zero every `NotIdentical`-tagged node anywhere in a substituted expression whose
two indices became equal. Nested occurrences matter: a `DoubleIndexedVariable`
with `identical=false` is almost always a factor in a larger product or sum, and
the surrounding `*`/`+` only collapses once that factor is replaced by zero.
"""
function _check_not_identical(result::SymbolicUtils.BasicSymbolic)
if SymbolicUtils.iscall(result) &&
SymbolicUtils.hasmetadata(result, NotIdentical) &&
length(SymbolicUtils.arguments(result)) == 2
a1, a2 = SymbolicUtils.arguments(result)
isequal(a1, a2) && return Num(0)
end
return Num(result)
zeros = _collect_identical_zeros!(Dict{SymbolicUtils.BasicSymbolic, Int}(), result)
isempty(zeros) && return Num(result)
return Num(Symbolics.substitute(result, zeros))
end
_check_not_identical(result::Number) = Num(result)

"""Accumulate into `acc` every `NotIdentical` node in `x` with two equal args, mapped to 0."""
function _collect_identical_zeros!(acc, x)
(x isa SymbolicUtils.BasicSymbolic && SymbolicUtils.iscall(x)) || return acc
if SymbolicUtils.hasmetadata(x, NotIdentical) &&
length(SymbolicUtils.arguments(x)) == 2
a1, a2 = SymbolicUtils.arguments(x)
# The args are indices, so a matched node holds no nested NotIdentical node.
isequal(a1, a2) && (acc[x] = 0; return acc)
end
for a in SymbolicUtils.arguments(x)
_collect_identical_zeros!(acc, a)
end
return acc
end

function _depends_on_index_term(c::CNum, ops::Vector{QSym}, idx::Index)
for op in ops
op.index == idx && return true
Expand Down
14 changes: 14 additions & 0 deletions test/expressions/indexing_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,20 @@ import SecondQuantizedAlgebra: simplify, QAdd, QSym, CNum, _to_cnum, NO_INDEX,
@test isequal(real(prefactor(mj)), gj)
end

@testset "change_index: nested identical=false collapses to 0" begin
i = Index(hf, :i, 10, hf)
j = Index(hf, :j, 10, hf)
@variables x
Jij = DoubleIndexedVariable(:J, i, j; identical = false) # 0 when i==j

# Bare node already worked; the regression is nested occurrences.
@test isequal(change_index(Jij, j, i), Symbolics.Num(0))
# Under a product: J(i,j)*x with j→i ⇒ J(i,i)=0 ⇒ whole product 0
@test isequal(change_index(Jij * x, j, i), Symbolics.Num(0))
# Under a sum: (J(i,j) + x) with j→i ⇒ x
@test isequal(change_index(Jij + x, j, i), x)
end

@testset "change_index — QAdd" begin
i = Index(hf, :i, 10, hf)
j = Index(hf, :j, 10, hf)
Expand Down
Loading