-
Notifications
You must be signed in to change notification settings - Fork 13
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
Implement inner(x,A,y)
for TTN
via BP
.
#146
Conversation
inner(x,A,y)
for TTN
via BP
.
O = O * ydag[v] * A[v] * x[v] | ||
end | ||
return O[] | ||
blf = BilinearFormNetwork(A, ydag, x) |
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 don't think we should be using a form here, that is mostly meant for optimization.
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.
Is your goal to make a tensor network out of the network y
, A
, and x
? If so, you can use disjoint_union
.
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.
Yes, as far as I understand the BilinearFormNetwork
just stacks the network here.
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.
Ok, let's do that without going through BilinearFormNetwork
.
) | ||
end | ||
|
||
function contract_with_BP( |
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.
contract_with_BP
isn't a good function name, what about overloading ITensors.contract(::Algorithm"bp", kwargs...)
and running with contract(itn; alg="bp", kwargs...)
.
end | ||
|
||
function contract_with_BP( | ||
T::Type, |
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'm confused by this part of the interface, why can you set the element type in this way?
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 is not the right way to do it. Basically, due to the log
in this implementation, we need to promote the scalars of which the element type is taken to complex
. Then the idea was that contract_with_BP
returns a complex scalar, unless you specify a type, in which case it converts the scalar to the specified type. This should of course be handled differently for a proper implementation as contract
with BP
backend.
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.
Ok. I think contract_with_BP
as it stands is too far away from being a library function, so we should think about how to deal with that before continuing forward with this PR.
if !is_tree(partitioned_graph(pg)) && outputlevel > 0 | ||
println("Partitioned graph is not a tree, result will be approximate!!") | ||
end |
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.
Let's remove this, I think this is inherent if someone selects that they are using BP.
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.
Yes, but it may be good to allow to pass a flag like assert_exact=true
, to check that the BP
will indeed be exact for the contraction (for the case of contracting TTN
s)?
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.
Let's think about the design of that, but I don't think we have to address that in this PR. I agree with the sentiment that we don't want to secretly perform approximate contractions but give users the impression that we are doing exact contractions.
for pv in partitionvertices(pg) | ||
incoming_mts = incoming_messages(bp_cache, [pv]) | ||
local_state = ITensor[itn[v] for v in vertices(pg, pv)] | ||
log_numerator += log(complex(ITensors.contract(vcat(incoming_mts, local_state))[])) |
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.
log_numerator += log(complex(ITensors.contract(vcat(incoming_mts, local_state))[])) | |
log_numerator += log(complex(contract(vcat(incoming_mts, local_state))[])) |
for pe in partitionedges(pg) | ||
log_denominator += log( | ||
complex( | ||
ITensors.contract(vcat(message(bp_cache, pe), message(bp_cache, reverse(pe))))[] |
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.
ITensors.contract(vcat(message(bp_cache, pe), message(bp_cache, reverse(pe))))[] | |
contract(vcat(message(bp_cache, pe), message(bp_cache, reverse(pe))))[] |
log_numerator, log_denominator = 0, 0 | ||
for pv in partitionvertices(pg) | ||
incoming_mts = incoming_messages(bp_cache, [pv]) | ||
local_state = ITensor[itn[v] for v in vertices(pg, pv)] |
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.
Can't you use pg[pv]
here?
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.
Or factor(bp_cache, pv)
?
end | ||
return O[] | ||
blf = BilinearFormNetwork(A, ydag, x) | ||
blf_scalar_bp = contract_with_BP( |
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.
If we just use contract
here, then we can allow an alg
keyword argument to get passed from inner
, and users can control what algorithm is used to contract the network.
To handle partitioning in the more general case, something we could do is that instead of passing an ITensorNetwork
and a partitioning, we pass a PartitionedGraph
to contract
, then it is up to the contract
backends to contract the partitioned tensor network (either using or ignoring the partitioning).
Closing in favor of first writing a better designed |
This implements
inner(x,A,y)
forx,A,y
allAbstractTTN
with the same underlying graph, passing through the BP-backend. It addresses a performance issue of the previous implementation for certainTTN
, leading to higher than necessary scaling in some situations (due to the traversal order). Thanks @JoeyT1994 for providing thecontract_with_BP
code.Tests have been added to
test_forms.jl
to verify the correctness of the implementation.This is not intended as a complete overhaul of the current implementations of
inner
,expect
etc, which could be addressed in future PRs.