+1 vote
asked by (200 points)

Hi,

I've been using the julia version of ITensor lately, and I noticed that calling DMRG by default does not print any information regarding the maximum truncation error for each sweep, unlike the C++ version. I've searched the documentation but could not find anything related to the truncation error. Is there some way to turn this feature on? Or is it just not implemented yet?

Best,

Rafael

commented by (70.1k points)
Hi Rafael,
Currently this feature just isn't implemented in the Julia version. Is it something you would be willing to contribute? In the C++ version it's implemented through the DMRGObserver type (in its measure function) which in Julia is all in the file src/mps/observer.jl.

Alternatively, if you want to keep track of the truncation error just in your own custom code, you can make a custom observer type as detailed on this documentation page:

https://itensor.github.io/ITensors.jl/stable/Observer.html


Miles
commented by (200 points)
Hi Miles,

Thanks for the reply. I will take a look into DMRGObserver and custom observers to see if I can implement it in a convenient way.

Best,

Rafael
commented by (70.1k points)
Great. Thanks for being open to trying that. If you find you get stuck or have questions along the way, please just post a reply here and I will see it, or email me.

Basically the pattern is that you should either alter DMRGObserver (and then send us a pull request to merge your changes) or make your own new observer, which could be modeled on DMRGObserver, that stores like a "max_trunc_err" variable inside it. Then before each sweep you would reset this to zero, and each time you get a report of the truncation error inside the `measure!` function (it is passed as one of the keyword arguments), you would call
max_trunc_err = max(max_trunc_err, truncerr)
to update max_trunc_err. At the end of the sweep you'd print out this value and again reset it to zero.

Miles
commented by (200 points)
Hi Miles,

I have tried following your directions but for some reason I am still unable to get the largest truncation error. I have created a new observer containing a max_trunc_err variable, and overloaded the measure! and checkdone! functions so that measure! does max_trunc_err = max(max_trunc_err, truncerr), and checkdone! prints the max_trunc_err and then resets its value to 0. From what I understand, it seems like the checkdone! function is only called at the end of a sweep, while the measure! function is called every step of every sweep, so I thought it should work. However, I always get a value of 0 for the largest truncation error. Here is a minimum working example:

    using ITensors

    mutable struct DemoObserver <: AbstractObserver
       max_trunc_err::Float64
    end

    function ITensors.measure!(obs::DemoObserver;kwargs...)
      truncerr = truncerror(kwargs[:spec])
      max_trunc_err=max(obs.max_trunc_err,truncerr)
    end

    function ITensors.checkdone!(obs::DemoObserver;kwargs...)
      println("Largest truncation error = ",obs.max_trunc_err)
      obs.max_trunc_err=0.0
      return false
    end

    let
      N = 10
      max_trunc_err = 0.0

      s = siteinds("S=1/2",N)

      a = AutoMPO()
      for n=1:N-1
        a += "Sz",n,"Sz",n+1
        a += 0.5,"S+",n,"S-",n+1
        a += 0.5,"S-",n,"S+",n+1
      end
      H = MPO(a,s)
      psi0 = randomMPS(s,4)

      sweeps = Sweeps(5)
      maxdim!(sweeps,10)

      obs = DemoObserver(max_trunc_err)

      println("Starting DMRG")
      energy, psi = dmrg(H,psi0,sweeps; observer=obs, outputlevel=1)

      return
    end


Do you know what I am doing wrong? Did I misunderstand how/where each of these functions are called?

Best,

Rafael
commented by (70.1k points)
Thanks for working on this. I think I see what the issue is. On the following line inside of measure!:

    max_trunc_err=max(obs.max_trunc_err,truncerr)

the variable max_trunc_err here is being created as a new local variable inside that function. It is not having the effect of updating the max_trunc_err inside of the obs object but just has the same name as that variable.

I think if you just change the line to:

    obs.max_trunc_err=max(obs.max_trunc_err,truncerr)

then it should work the way you expect.
commented by (70.1k points)
By the way that's clever to put the printout into the checkdone! function. I had not thought of using it that way. Normally what I would have done is to get the info about what bond and half-sweep one is on from the keyword args to the measure! function. Then if the bond is 1 and the half-sweep number is 2, it means we are at the end of a sweep. But using checkdone! is much simpler and a totally good way to do it.
commented by (200 points)
Thanks, it is working as intended!

Now I would like to implement something that works like this inside the observer.jl file, so that I don't have to overload the measure! and checkdone! functions every time I want to check the truncation error. Do you think it would be better to change the DMRGObserver struct or to just add this new custom observer to the file?
commented by (70.1k points)
Hi Rafael,
So I hope this isn't frustrating news but, prompted by your question, I finally added the reporting of the max truncation error to our DMRG code today. (It's in a pending pull request that I will merge.)

However, I still hope the code you wrote can be useful to you if you want to customize the output even more. You wouldn't really have to overload the measure! and checkdone! functions every time because you can just put this code into a file (demoobserver.jl, say) and then put include("demoobserver.jl") into your main code. Then the only thing you have to do is just construct and pass your observer to the dmrg function if you want to use it. So it shouldn't be too much harder than if it was built into ITensor.

Of course if you do have a change for the provided observers you'd like to make, we welcome that and would be happy to accept a PR from you, and best to run the change by us first to see if it's along the lines of the designs we want.

Thanks,
Miles
commented by (200 points)
No problem at all, thanks for helping me out and quickly addressing the issue!
commented by (70.1k points)
Great. Looking forward to chatting more in the future -

Miles

Please log in or register to answer this question.

Welcome to ITensor Support Q&A, where you can ask questions and receive answers from other members of the community.

Formatting Tips:
  • To format code, indent by four spaces
  • To format inline LaTeX, surround it by @@ on both sides
  • To format LaTeX on its own line, surround it by $$ above and below
  • For LaTeX, it may be necessary to backslash-escape underscore characters to obtain proper formatting. So for example writing \sum\_i to represent a sum over i.
If you cannot register due to firewall issues (e.g. you cannot see the capcha box) please email Miles Stoudenmire to ask for an account.

To report ITensor bugs, please use the issue tracker.

Categories

...