-
Notifications
You must be signed in to change notification settings - Fork 10
feat(templates): Implement unified lattice module and tests #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(templates): Implement unified lattice module and tests #18
Conversation
184eae4
to
366bba1
Compare
This update primarily refactors the plotting logic within the show() method to resolve a persistent mypy [arg-type] error related to ax.text(). Instead of simply suppressing the error with # type: ignore, I opted for a more robust solution by using isinstance(ax, Axes3D) to perform a direct, type-safe check on the Matplotlib axes object. This approach makes the code's intent clearer to static analysis tools and fixes the type ambiguity cleanly. I thought this time my code may pass the mypy test . |
366bba1
to
c80e14c
Compare
Following the guidance of pylint , I fix my code . |
some more TILattice, |
please also modify init.py in templates module accordingly |
c80e14c
to
51fda8a
Compare
Hi @refraction-ray, Thank you again for your invaluable guidance and detailed review. I have now pushed the updates, incorporating all of your feedback. Here is a summary of the main changes:
|
Thanks for the nice contribution. In general, the code looks very good. The addition should be a more robust and error-free neighbor searching implementation with careful consideration on PBC and large current failed case for neighbor search: sq = lattice.SquareLattice(size=(4,4), pbc=True)
len(sq.get_neighbor_pairs(k=3))
# 0 Considering that the typical total size of the lattice used in tensorcircuit is 10-1000, it may be straightforward and robust to directly precompute the all-to-all full distance matrix with the real space distance in terms of pbc (see Minimum Image Convention method). There might be corner case with mixed boundary conditions and skewed lattice vector not align with pbc dimensions, let us just ignore such pathological cases. |
51fda8a
to
2e2bd32
Compare
Hi @refraction-ray, |
@refraction-ray Fixed. I've pushed the commit to add the missing docstring. Thanks for the review. |
Very impressive and responsive work!
sq = SquareLattice([3, 3])
cl = CustomizeLattice.from_lattice(sq)
cl.add_sites(identifies, coordinates)
# error when identifies is duplicated internally
cl.remove_sites(identifies) Again, the contribution overall looks very nice and impressive to me. (The current CI error is irrelevant from your commits, just ignore it) |
982e4be
to
6fb16e9
Compare
Hi @refraction-ray I ran a performance benchmark for the neighbor finding methods. The data shows that the KDTree-based method is likely consistently faster. Based on this, I've kept the implementation simple, using KDTree by default without needing a user-facing switch. The benchmark script is included in templates/ .benchmarks/. New tests for all new features have been added. |
while assisted with AI is okay, please ensure the change is necessary and minimal, (say obviously the frequent docstring & comment & variable name change is meaningless and gives negative contribution to code review as the diff is large). The latest commit, while indeed contains the |
@refraction-ray |
@Stellogic , No need to apologize. It is super okay to use AI, actually I strongly recommend you guys to intensively use AI for coding and development tasks. Just pay attention to the points I mention, as a large bulk of unnecessary changes will make the code review more difficult. AI can write the code for the most parts and everyone use it. It is a good thing, but you should be the first responsible reviewer for what AI generates and changes :) |
f79c488
to
6eb21c3
Compare
Hi @refraction-ray, Following your guidance, I have force-pushed an update. I've reset the branch back to commit 9ef578d and built a single, clean commit on top of it containing only the necessary fixes to address the test failures. This new commit includes three targeted fixes: Fixed Distance Matrix Caching for TILattice: In the fully periodic case, _build_neighbors now reconstructs and caches the full distance matrix by leveraging the existing ref_dist_matrix_sq and translational symmetry. This resolves all failures in TestDistanceMatrix. Fixed Neighbor Finding for Duplicate Coordinates in Improved Numerical Stability in _identify_distance_shells: The logic for filtering zero-distance points has been decoupled from the tolerance-based shell identification. It now robustly filters out self-loops using a fixed small threshold (1e-12), resolving the test_neighbor_shells_with_tiny_separation failure. |
tensorcircuit/templates/lattice.py
Outdated
unique_sorted_dist = sorted( | ||
[d for d in np.unique(all_distances_sq) if d > tol**2] | ||
) | ||
sorted_dist = np.sort(all_distances_sq[all_distances_sq > 1e-12]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tol**2
instead of 1e-12?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've looked into this, and it seems that a direct replacement with tol2 causes the test_neighbor_shells_with_tiny_separation test to fail.
The root cause seemms that tol is treated as a linear distance tolerance, but using tol2 in the squared-distance comparison logic makes the shell-merging behavior overly sensitive and breaks the test's intent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Stellogic it is weird, as tol**2 = 1e-6**2
is just 1e-12? what makes the difference? otherwise, what is the point for the tol argument?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
besides, if the 1e-12 has no dependce on tol
, how the test you mention can differentiate the two cases with different tol
6eb21c3
to
dcd316a
Compare
Hi @refraction-ray, I've pushed the new commit addressing your feedback. The indentation issue with the _distance_matrix assignment has been fixed as you suggested. But I've kept the 1e-12 implementation. The reason is that changing it to tol**2 causes the numerical stability test (test_neighbor_shells_with_tiny_separation) to fail. |
c73644a
to
dcd316a
Compare
the CI error seems to be irrelevant for this PR. However, I am still confused on the success of |
tensorcircuit/templates/lattice.py
Outdated
relative_ucs_list = [ | ||
cast(Tuple[Any, ...], ident)[:-1] for ident in self._identifiers | ||
] | ||
relative_ucs_arr = np.array(relative_ucs_list) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be outside the for as it doesn't depend on i?
tensorcircuit/templates/lattice.py
Outdated
all_target_ucs[:, dim] %= size_arr[dim] | ||
|
||
# Convert these relative unit cell coordinates back to site indices | ||
all_target_basis = np.array( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should also be outside the for and created only once?
tensorcircuit/templates/lattice.py
Outdated
neighbor_templates[source_basis_idx][k].append((uc_disp, target_basis)) | ||
|
||
# 4. Apply the templates to all sites in the lattice | ||
self._neighbor_maps = {k: {} for k in range(1, len(dist_shells_sq) + 1)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
max_k
or len(dist_shells_sq)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sq = lattice.HoneycombLattice(size=(4,5), pbc=True, precompute_neighbors=1)
sq._neighbor_maps # now a full map instead of max_k = 1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
currently both pbc and obc in TILattice automatically build the whole neighbor maps with invalid max_k
or precompute_neighbors
the mixed boundary condition universal implementation is efficient enough, just deleting the special tailored implementation branch for fully PBC case, and everything would be nicer and easier |
overall,
|
This commit addresses feedback from the code review, focusing on performance, clarity, and robustness. - Removes the complex and slow PBC-specific algorithm in `TILattice._build_neighbors`. All boundary conditions now use a unified, faster, and simpler MIC-based method. This resolves the major performance regression issue. - Replaces the hardcoded `1e-12` with a named constant `ZERO_THRESHOLD_SQ` in `_identify_distance_shells` to clarify its role as a zero-cutoff threshold, distinct from the `tol` parameter. - Strengthens the test suite by adding: - A performance regression test to ensure PBC implementation remains efficient. - A parameterized state test to verify `max_k` functionality in both `TILattice` and `CustomizeLattice`.
Hi@refraction-ray! To clarify the point about 1e-12: it is indeed intended to handle floating-point precision issues by filtering out squared distances that are effectively zero. This is a fixed threshold and is independent of the tol parameter, which is used for separating distinct neighbor shells. The test_neighbor_shells_with_tiny_separation test, which passes various tol values, demonstrates this intended separation of concerns. I've also strengthened the test suite with two additions: A performance regression test to ensure we don't encounter performance degradation in the future. |
looks good to me now, thanks for the nice contribution! will merge soon |
@all-contributors please add @Stellogic for code, examples, tests |
I've put up a pull request to add @Stellogic! 🎉 |
Apart from some more tutorials and examples, the next key milestone could be a machine learning backend agnostic implementation for lattice module, compared to the numpy backend implementation now. A backend agnostic implementation using tensorcircuit.backend API would enable automatic differentiation, vectorized map etc. for this lattice module. A typical example is structure optimization, where the energy computed from the lattice is minimized via gradient descent with tunable parameters the lattice structure parameters. |
Hi @refraction-ray, |
Hi @yutuer21,
Following your guidance and the OSPP project requirements ("Object-Oriented Lattice Generation"), I've prepared this initial pull request to add the unified lattice module. I would be grateful for your review and feedback.
Main Changes in this PR:
AbstractLattice
: An abstract base class is proposed to define the common API.CustomizeLattice
andTILattice
(withSquareLattice
,HoneycombLattice
,TriangularLattice
examples) are provided as initial implementations.get_site_info()
,get_neighbors()
, and.show()
visualization are included.tests/test_lattice.py
) has been added to cover the core functions and edge cases, achieving ~94% coverage onlattice.py
.CHANGELOG.md
has been updated.This is the first version based on my understanding of the requirements, and I'm sure there is still much room for improvement. Thank you very much for your valuable time and guidance. I look forward to your feedback!