<commit_before>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2012] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/
#ifndef REALM_UTIL_BUFFER_HPP
#define REALM_UTIL_BUFFER_HPP

#include <cstddef>
#include <algorithm>
#include <exception>
#include <limits>
#include <utility>

#include <realm/util/features.h>
#include <realm/util/safe_int_ops.hpp>
#include <memory>

namespace realm {
namespace util {

/// A simple buffer concept that owns a region of memory and knows its
/// size.
template<class T> class Buffer {
public:
    Buffer() REALM_NOEXCEPT: m_data(0), m_size(0) {}
    Buffer(std::size_t size);
    ~Buffer() REALM_NOEXCEPT {}

    T& operator[](std::size_t i) REALM_NOEXCEPT { return m_data[i]; }
    const T& operator[](std::size_t i) const REALM_NOEXCEPT { return m_data[i]; }

    T* data() REALM_NOEXCEPT { return m_data.get(); }
    const T* data() const REALM_NOEXCEPT { return m_data.get(); }
    std::size_t size() const REALM_NOEXCEPT { return m_size; }

    /// Discards the original contents.
    void set_size(std::size_t new_size);

    /// \param copy_begin, copy_end Specifies a range of element
    /// values to be retained. \a copy_end must be less than, or equal
    /// to size().
    ///
    /// \param copy_to Specifies where the retained range should be
    /// copied to. `\a copy_to + \a copy_end - \a copy_begin` must be
    /// less than, or equal to \a new_size.
    void resize(std::size_t new_size, std::size_t copy_begin, std::size_t copy_end,
                std::size_t copy_to);

    void reserve(std::size_t used_size, std::size_t min_capacity);

    void reserve_extra(std::size_t used_size, std::size_t min_extra_capacity);

    T* release() REALM_NOEXCEPT;

    friend void swap(Buffer&a, Buffer&b) REALM_NOEXCEPT
    {
        using std::swap;
        swap(a.m_data, b.m_data);
        swap(a.m_size, b.m_size);
    }

private:
    std::unique_ptr<T[]> m_data;
    std::size_t m_size;
};

/// A buffer that can be efficiently resized. It acheives this by
/// using an underlying buffer that may be larger than the logical
/// size, and is automatically expanded in progressively larger steps.
template<class T> class AppendBuffer {
public:
    AppendBuffer() REALM_NOEXCEPT;
    ~AppendBuffer() REALM_NOEXCEPT {}

    /// Returns the current size of the buffer.
    std::size_t size() const REALM_NOEXCEPT;

    /// Gives read and write access to the elements.
    T* data() REALM_NOEXCEPT;

    /// Gives read access the elements.
    const T* data() const REALM_NOEXCEPT;

    /// Append the specified elements. This increases the size of this
    /// buffer by \a size. If the caller has previously requested a
    /// minimum capacity that is greater than, or equal to the
    /// resulting size, this function is guaranteed to not throw.
    void append(const T* data, std::size_t size);

    /// If the specified size is less than the current size, then the
    /// buffer contents is truncated accordingly. If the specified
    /// size is greater than the current size, then the extra elements
    /// will have undefined values. If the caller has previously
    /// requested a minimum capacity that is greater than, or equal to
    /// the specified size, this function is guaranteed to not throw.
    void resize(std::size_t size);

    /// This operation does not change the size of the buffer as
    /// returned by size(). If the specified capacity is less than the
    /// current capacity, this operation has no effect.
    void reserve(std::size_t min_capacity);

    /// Set the size to zero. The capacity remains unchanged.
    void clear() REALM_NOEXCEPT;

private:
    util::Buffer<char> m_buffer;
    std::size_t m_size;
};

// Implementation:

class BufferSizeOverflow: public std::exception {
public:
    const char* what() const REALM_NOEXCEPT_OR_NOTHROW REALM_OVERRIDE
    {
        return "Buffer size overflow";
    }
};

template<class T> inline Buffer<T>::Buffer(std::size_t size):
    m_data(new T[size]), // Throws
    m_size(size)
{
}

template<class T> inline void Buffer<T>::set_size(std::size_t new_size)
{
    m_data.reset(new T[new_size]); // Throws
    m_size = new_size;
}

template<class T> inline void Buffer<T>::resize(std::size_t new_size, std::size_t copy_begin,
                                                std::size_t copy_end, std::size_t copy_to)
{
    std::unique_ptr<T[]> new_data(new T[new_size]); // Throws
    std::copy(m_data.get() + copy_begin, m_data.get() + copy_end, new_data.get() + copy_to);
    m_data.reset(new_data.release());
    m_size = new_size;
}

template<class T> inline void Buffer<T>::reserve(std::size_t used_size,
                                                 std::size_t min_capacity)
{
    std::size_t current_capacity = m_size;
    if (REALM_LIKELY(current_capacity >= min_capacity))
        return;
    std::size_t new_capacity = current_capacity;
    if (REALM_UNLIKELY(int_multiply_with_overflow_detect(new_capacity, 2)))
        new_capacity = std::numeric_limits<std::size_t>::max();
    if (REALM_UNLIKELY(new_capacity < min_capacity))
        new_capacity = min_capacity;
    resize(new_capacity, 0, used_size, 0); // Throws
}

template<class T> inline void Buffer<T>::reserve_extra(std::size_t used_size,
                                                       std::size_t min_extra_capacity)
{
    std::size_t min_capacity = used_size;
    if (REALM_UNLIKELY(int_add_with_overflow_detect(min_capacity, min_extra_capacity)))
        throw BufferSizeOverflow();
    reserve(used_size, min_capacity); // Throws
}

template<class T> inline T* Buffer<T>::release() REALM_NOEXCEPT
{
    m_size = 0;
    return m_data.release();
}

template<class T> inline AppendBuffer<T>::AppendBuffer() REALM_NOEXCEPT: m_size(0)
{
}

template<class T> inline std::size_t AppendBuffer<T>::size() const REALM_NOEXCEPT
{
    return m_size;
}

template<class T> inline T* AppendBuffer<T>::data() REALM_NOEXCEPT
{
    return m_buffer.data();
}

template<class T> inline const T* AppendBuffer<T>::data() const REALM_NOEXCEPT
{
    return m_buffer.data();
}

template<class T> inline void AppendBuffer<T>::append(const T* data, std::size_t size)
{
    m_buffer.reserve_extra(m_size, size); // Throws
    std::copy(data, data+size, m_buffer.data()+m_size);
    m_size += size;
}

template<class T> inline void AppendBuffer<T>::reserve(std::size_t min_capacity)
{
    m_buffer.reserve(m_size, min_capacity);
}

template<class T> inline void AppendBuffer<T>::resize(std::size_t size)
{
    reserve(size);
    m_size = size;
}

template<class T> inline void AppendBuffer<T>::clear() REALM_NOEXCEPT
{
    m_size = 0;
}

} // namespace util
} // namespace realm

#endif // REALM_UTIL_BUFFER_HPP
<commit_msg>disambiguate null ptr<commit_after>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2012] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/
#ifndef REALM_UTIL_BUFFER_HPP
#define REALM_UTIL_BUFFER_HPP

#include <cstddef>
#include <algorithm>
#include <exception>
#include <limits>
#include <utility>

#include <realm/util/features.h>
#include <realm/util/safe_int_ops.hpp>
#include <memory>

namespace realm {
namespace util {

/// A simple buffer concept that owns a region of memory and knows its
/// size.
template<class T> class Buffer {
public:
    Buffer() REALM_NOEXCEPT: m_data(nullptr), m_size(0) {}
    Buffer(std::size_t size);
    ~Buffer() REALM_NOEXCEPT {}

    T& operator[](std::size_t i) REALM_NOEXCEPT { return m_data[i]; }
    const T& operator[](std::size_t i) const REALM_NOEXCEPT { return m_data[i]; }

    T* data() REALM_NOEXCEPT { return m_data.get(); }
    const T* data() const REALM_NOEXCEPT { return m_data.get(); }
    std::size_t size() const REALM_NOEXCEPT { return m_size; }

    /// Discards the original contents.
    void set_size(std::size_t new_size);

    /// \param copy_begin, copy_end Specifies a range of element
    /// values to be retained. \a copy_end must be less than, or equal
    /// to size().
    ///
    /// \param copy_to Specifies where the retained range should be
    /// copied to. `\a copy_to + \a copy_end - \a copy_begin` must be
    /// less than, or equal to \a new_size.
    void resize(std::size_t new_size, std::size_t copy_begin, std::size_t copy_end,
                std::size_t copy_to);

    void reserve(std::size_t used_size, std::size_t min_capacity);

    void reserve_extra(std::size_t used_size, std::size_t min_extra_capacity);

    T* release() REALM_NOEXCEPT;

    friend void swap(Buffer&a, Buffer&b) REALM_NOEXCEPT
    {
        using std::swap;
        swap(a.m_data, b.m_data);
        swap(a.m_size, b.m_size);
    }

private:
    std::unique_ptr<T[]> m_data;
    std::size_t m_size;
};

/// A buffer that can be efficiently resized. It acheives this by
/// using an underlying buffer that may be larger than the logical
/// size, and is automatically expanded in progressively larger steps.
template<class T> class AppendBuffer {
public:
    AppendBuffer() REALM_NOEXCEPT;
    ~AppendBuffer() REALM_NOEXCEPT {}

    /// Returns the current size of the buffer.
    std::size_t size() const REALM_NOEXCEPT;

    /// Gives read and write access to the elements.
    T* data() REALM_NOEXCEPT;

    /// Gives read access the elements.
    const T* data() const REALM_NOEXCEPT;

    /// Append the specified elements. This increases the size of this
    /// buffer by \a size. If the caller has previously requested a
    /// minimum capacity that is greater than, or equal to the
    /// resulting size, this function is guaranteed to not throw.
    void append(const T* data, std::size_t size);

    /// If the specified size is less than the current size, then the
    /// buffer contents is truncated accordingly. If the specified
    /// size is greater than the current size, then the extra elements
    /// will have undefined values. If the caller has previously
    /// requested a minimum capacity that is greater than, or equal to
    /// the specified size, this function is guaranteed to not throw.
    void resize(std::size_t size);

    /// This operation does not change the size of the buffer as
    /// returned by size(). If the specified capacity is less than the
    /// current capacity, this operation has no effect.
    void reserve(std::size_t min_capacity);

    /// Set the size to zero. The capacity remains unchanged.
    void clear() REALM_NOEXCEPT;

private:
    util::Buffer<char> m_buffer;
    std::size_t m_size;
};

// Implementation:

class BufferSizeOverflow: public std::exception {
public:
    const char* what() const REALM_NOEXCEPT_OR_NOTHROW REALM_OVERRIDE
    {
        return "Buffer size overflow";
    }
};

template<class T> inline Buffer<T>::Buffer(std::size_t size):
    m_data(new T[size]), // Throws
    m_size(size)
{
}

template<class T> inline void Buffer<T>::set_size(std::size_t new_size)
{
    m_data.reset(new T[new_size]); // Throws
    m_size = new_size;
}

template<class T> inline void Buffer<T>::resize(std::size_t new_size, std::size_t copy_begin,
                                                std::size_t copy_end, std::size_t copy_to)
{
    std::unique_ptr<T[]> new_data(new T[new_size]); // Throws
    std::copy(m_data.get() + copy_begin, m_data.get() + copy_end, new_data.get() + copy_to);
    m_data.reset(new_data.release());
    m_size = new_size;
}

template<class T> inline void Buffer<T>::reserve(std::size_t used_size,
                                                 std::size_t min_capacity)
{
    std::size_t current_capacity = m_size;
    if (REALM_LIKELY(current_capacity >= min_capacity))
        return;
    std::size_t new_capacity = current_capacity;
    if (REALM_UNLIKELY(int_multiply_with_overflow_detect(new_capacity, 2)))
        new_capacity = std::numeric_limits<std::size_t>::max();
    if (REALM_UNLIKELY(new_capacity < min_capacity))
        new_capacity = min_capacity;
    resize(new_capacity, 0, used_size, 0); // Throws
}

template<class T> inline void Buffer<T>::reserve_extra(std::size_t used_size,
                                                       std::size_t min_extra_capacity)
{
    std::size_t min_capacity = used_size;
    if (REALM_UNLIKELY(int_add_with_overflow_detect(min_capacity, min_extra_capacity)))
        throw BufferSizeOverflow();
    reserve(used_size, min_capacity); // Throws
}

template<class T> inline T* Buffer<T>::release() REALM_NOEXCEPT
{
    m_size = 0;
    return m_data.release();
}

template<class T> inline AppendBuffer<T>::AppendBuffer() REALM_NOEXCEPT: m_size(0)
{
}

template<class T> inline std::size_t AppendBuffer<T>::size() const REALM_NOEXCEPT
{
    return m_size;
}

template<class T> inline T* AppendBuffer<T>::data() REALM_NOEXCEPT
{
    return m_buffer.data();
}

template<class T> inline const T* AppendBuffer<T>::data() const REALM_NOEXCEPT
{
    return m_buffer.data();
}

template<class T> inline void AppendBuffer<T>::append(const T* data, std::size_t size)
{
    m_buffer.reserve_extra(m_size, size); // Throws
    std::copy(data, data+size, m_buffer.data()+m_size);
    m_size += size;
}

template<class T> inline void AppendBuffer<T>::reserve(std::size_t min_capacity)
{
    m_buffer.reserve(m_size, min_capacity);
}

template<class T> inline void AppendBuffer<T>::resize(std::size_t size)
{
    reserve(size);
    m_size = size;
}

template<class T> inline void AppendBuffer<T>::clear() REALM_NOEXCEPT
{
    m_size = 0;
}

} // namespace util
} // namespace realm

#endif // REALM_UTIL_BUFFER_HPP
<|endoftext|>


<commit_before>// -*- c++ -*-
/********************************************************************
 * AUTHORS: Vijay Ganesh
 *
 * BEGIN DATE: November, 2005
 *
 * LICENSE: Please view LICENSE file in the home dir of this Program
 ********************************************************************/
#include "ToSAT.h"

namespace BEEV
{
  /* FUNCTION: lookup or create a new MINISAT literal
   * lookup or create new MINISAT Vars from the global MAP
   * _ASTNode_to_SATVar.
   */
  MINISAT::Var
  ToSAT::LookupOrCreateSATVar(MINISAT::Solver& newS, const ASTNode& n)
  {
    ASTtoSATMap::iterator it;
    MINISAT::Var v;

    //look for the symbol in the global map from ASTNodes to ints. if
    //not found, create a S.newVar(), else use the existing one.
    if ((it = _ASTNode_to_SATVar_Map.find(n)) == _ASTNode_to_SATVar_Map.end())
      {
        v = newS.newVar();
        _ASTNode_to_SATVar_Map[n] = v;

        //ASSUMPTION: I am assuming that the newS.newVar() call increments v
        //by 1 each time it is called, and the initial value of a
        //MINISAT::Var is 0.
        _SATVar_to_AST_Vector.push_back(n);
      }
    else
      v = it->second;
    return v;
  }

  /* FUNCTION: convert ASTClauses to MINISAT clauses and solve.
   * Accepts ASTClauses and converts them to MINISAT clauses. Then
   * adds the newly minted MINISAT clauses to the local SAT instance,
   * and calls solve(). If solve returns unsat, then stop and return
   * unsat. else continue.
   */
  bool ToSAT::toSATandSolve(MINISAT::Solver& newS, ClauseList& cll)
  {
    CountersAndStats("SAT Solver", bm);
    bm->GetRunTimes()->start(RunTimes::SendingToSAT);

    int input_clauselist_size = cll.size();
    if (cll.size() == 0)
      {
	FatalError("toSATandSolve: Nothing to Solve", ASTUndefined);
      }

#ifdef CRYPTOMINISAT
    newS.startClauseAdding();
#endif
    //iterate through the list (conjunction) of ASTclauses cll
    ClauseList::const_iterator i = cll.begin(), iend = cll.end();
    for (int count=0, flag=0; i != iend; i++)
      {
        //Clause for the SATSolver
        MINISAT::vec<MINISAT::Lit> satSolverClause;
        satSolverClause.capacity((*i)->size());
        vector<const ASTNode*>::const_iterator j    = (*i)->begin();
        vector<const ASTNode*>::const_iterator jend = (*i)->end();
	//ASTVec  clauseVec;
        //j is a disjunct in the ASTclause (*i)
        for (; j != jend; j++)
          {
            ASTNode node = **j;
	    //clauseVec.push_back(node);
            bool negate = (NOT == node.GetKind()) ? true : false;
            ASTNode n = negate ? node[0] : node;
            MINISAT::Var v = LookupOrCreateSATVar(newS, n);
            MINISAT::Lit l(v, negate);
            satSolverClause.push(l);
          }

        // ASTNode theClause = bm->CreateNode(OR, clauseVec);
	// 	if(flag
	// 	   && ASTTrue == CheckBBandCNF(newS, theClause))
	// 	  {
	// 	    continue;
	// 	  }

	newS.addClause(satSolverClause);
	float percentage=0.6;
	if(count++ >= input_clauselist_size*percentage)
	  {
	    //Arbitrary adding only 60% of the clauses in the hopes of
	    //terminating early
	    // 	    cout << "Percentage clauses added: "
	    // 		 << percentage << endl;
	    bm->GetRunTimes()->stop(RunTimes::SendingToSAT);
		bm->GetRunTimes()->start(RunTimes::Solving);
	    newS.solve();
	    bm->GetRunTimes()->stop(RunTimes::Solving);
	    if(!newS.okay())
	      {
		return false;
	      }
	    count = 0;
	    flag  = 1;
    	bm->GetRunTimes()->start(RunTimes::SendingToSAT);
	  }
        if (newS.okay())
          {
        	continue;
          }
        else
          {
            bm->PrintStats(newS);
            bm->GetRunTimes()->stop(RunTimes::SendingToSAT);
            return false;
          }
      } // End of For-loop adding the clauses

    bm->GetRunTimes()->stop(RunTimes::SendingToSAT);
    //cout << "Added remaining clauses\n";
    bm->GetRunTimes()->start(RunTimes::Solving);
    newS.solve();
    bm->GetRunTimes()->stop(RunTimes::Solving);
    bm->PrintStats(newS);
    if (newS.okay())
      return true;
    else
      return false;
  } //end of toSATandSolve()

  // Looks up truth value of ASTNode SYMBOL in MINISAT satisfying
  // assignment.  Returns ASTTrue if true, ASTFalse if false or
  // undefined.
  ASTNode ToSAT::SymbolTruthValue(MINISAT::Solver &newS, ASTNode form)
  {
    MINISAT::Var satvar = _ASTNode_to_SATVar_Map[form];
    if (newS.model[satvar] == MINISAT::l_True)
      {
        return ASTTrue;
      }
    else
      {
        // False or undefined.
        return ASTFalse;
      }
  }

  // This function is for debugging problems with BitBlast and
  // especially ToCNF. It evaluates the bit-blasted formula in the
  // satisfying assignment.  While doing that, it checks that every
  // subformula has the same truth value as its representative
  // literal, if it has one.  If this condition is violated, it halts
  // immediately (on the leftmost lowest term).  Use CreateSimpForm to
  // evaluate, even though it's expensive, so that we can use the
  // partial truth assignment.
  ASTNode ToSAT::CheckBBandCNF(MINISAT::Solver& newS, ASTNode form)
  {
    // Clear memo table (in case newS has changed).
    CheckBBandCNFMemo.clear();
    // Call recursive version that does the work.
    return CheckBBandCNF_int(newS, form);
  } //End of CheckBBandCNF()

  // Recursive body CheckBBandCNF
  ASTNode ToSAT::CheckBBandCNF_int(MINISAT::Solver& newS, ASTNode form)
  {
    //     cout << "++++++++++++++++"
    // 	 << endl
    // 	 << "CheckBBandCNF_int form = "
    // 	 << form << endl;

    ASTNodeMap::iterator memoit = CheckBBandCNFMemo.find(form);
    if (memoit != CheckBBandCNFMemo.end())
      {
        // found it.  Return memoized value.
        return memoit->second;
      }

    ASTNode result; // return value, to memoize.

    Kind k = form.GetKind();
    switch (k)
      {
      case TRUE:
      case FALSE:
        {
          return form;
          break;
        }
      case SYMBOL:
      case BVGETBIT:
        {
          result = SymbolTruthValue(newS, form);

	  //           cout << "================"
	  //                << endl
	  //                << "Checking BB formula:"
	  //                << form << endl;
	  //           cout << "----------------"
	  //                << endl
	  //                << "Result:" << result << endl;
          break;
        }
      default:
        {
          // Evaluate the children recursively.
          ASTVec eval_children;
          ASTVec ch = form.GetChildren();
          ASTVec::iterator itend = ch.end();
          for (ASTVec::iterator it = ch.begin(); it < itend; it++)
            {
              eval_children.push_back(CheckBBandCNF_int(newS, *it));
            }
          result = bm->CreateSimpForm(k, eval_children);

	  //           cout << "================"
	  //                << endl
	  //                << "Checking BB formula:" << form << endl;
	  //           cout << "----------------"
	  //                << endl
	  //                << "Result:" << result << endl;

          ASTNode replit_eval;
          // Compare with replit, if there is one.
          ASTNodeMap::iterator replit_it = RepLitMap.find(form);
          if (replit_it != RepLitMap.end())
            {
              ASTNode replit = RepLitMap[form];
              // Replit is symbol or not symbol.
              if (SYMBOL == replit.GetKind())
                {
                  replit_eval = SymbolTruthValue(newS, replit);
                }
              else
                {
                  // It's (NOT sym).  Get value of sym and complement.
                  replit_eval =
                    bm->CreateSimpNot(SymbolTruthValue(newS, replit[0]));
                }

	      //               cout << "----------------"
	      //                    << endl
	      //                    << "Rep lit: " << replit << endl;
	      //               cout << "----------------"
	      //                    << endl
	      //                    << "Rep lit value: " << replit_eval << endl;

              if (result != replit_eval)
                {
                  // Hit the panic button.
                  FatalError("Truth value of BitBlasted formula "\
                             "disagrees with representative literal in CNF.");
                }
            }
          else
            {
              //cout << "----------------" << endl << "No rep lit" << endl;
            }

        }
      }

    return (CheckBBandCNFMemo[form] = result);
  } //end of CheckBBandCNF_int()
}; //end of namespace BEEV
<commit_msg>changed the undefined return value from MINISAT to True. Saves 30% on all regressions<commit_after>// -*- c++ -*-
/********************************************************************
 * AUTHORS: Vijay Ganesh
 *
 * BEGIN DATE: November, 2005
 *
 * LICENSE: Please view LICENSE file in the home dir of this Program
 ********************************************************************/
#include "ToSAT.h"

namespace BEEV
{
  /* FUNCTION: lookup or create a new MINISAT literal
   * lookup or create new MINISAT Vars from the global MAP
   * _ASTNode_to_SATVar.
   */
  MINISAT::Var
  ToSAT::LookupOrCreateSATVar(MINISAT::Solver& newS, const ASTNode& n)
  {
    ASTtoSATMap::iterator it;
    MINISAT::Var v;

    //look for the symbol in the global map from ASTNodes to ints. if
    //not found, create a S.newVar(), else use the existing one.
    if ((it = _ASTNode_to_SATVar_Map.find(n)) == _ASTNode_to_SATVar_Map.end())
      {
        v = newS.newVar();
        _ASTNode_to_SATVar_Map[n] = v;

        //ASSUMPTION: I am assuming that the newS.newVar() call increments v
        //by 1 each time it is called, and the initial value of a
        //MINISAT::Var is 0.
        _SATVar_to_AST_Vector.push_back(n);
      }
    else
      v = it->second;
    return v;
  }

  /* FUNCTION: convert ASTClauses to MINISAT clauses and solve.
   * Accepts ASTClauses and converts them to MINISAT clauses. Then
   * adds the newly minted MINISAT clauses to the local SAT instance,
   * and calls solve(). If solve returns unsat, then stop and return
   * unsat. else continue.
   */
  bool ToSAT::toSATandSolve(MINISAT::Solver& newS, ClauseList& cll)
  {
    CountersAndStats("SAT Solver", bm);
    bm->GetRunTimes()->start(RunTimes::SendingToSAT);

    int input_clauselist_size = cll.size();
    if (cll.size() == 0)
      {
	FatalError("toSATandSolve: Nothing to Solve", ASTUndefined);
      }

#ifdef CRYPTOMINISAT
    newS.startClauseAdding();
#endif
    //iterate through the list (conjunction) of ASTclauses cll
    ClauseList::const_iterator i = cll.begin(), iend = cll.end();
    for (int count=0, flag=0; i != iend; i++)
      {
        //Clause for the SATSolver
        MINISAT::vec<MINISAT::Lit> satSolverClause;
        satSolverClause.capacity((*i)->size());
        vector<const ASTNode*>::const_iterator j    = (*i)->begin();
        vector<const ASTNode*>::const_iterator jend = (*i)->end();
	//ASTVec  clauseVec;
        //j is a disjunct in the ASTclause (*i)
        for (; j != jend; j++)
          {
            ASTNode node = **j;
	    //clauseVec.push_back(node);
            bool negate = (NOT == node.GetKind()) ? true : false;
            ASTNode n = negate ? node[0] : node;
            MINISAT::Var v = LookupOrCreateSATVar(newS, n);
            MINISAT::Lit l(v, negate);
            satSolverClause.push(l);
          }

        // ASTNode theClause = bm->CreateNode(OR, clauseVec);
	// 	if(flag
	// 	   && ASTTrue == CheckBBandCNF(newS, theClause))
	// 	  {
	// 	    continue;
	// 	  }

	newS.addClause(satSolverClause);
	float percentage=0.6;
	if(count++ >= input_clauselist_size*percentage)
	  {
	    //Arbitrary adding only 60% of the clauses in the hopes of
	    //terminating early
	    // 	    cout << "Percentage clauses added: "
	    // 		 << percentage << endl;
	    bm->GetRunTimes()->stop(RunTimes::SendingToSAT);
		bm->GetRunTimes()->start(RunTimes::Solving);
	    newS.solve();
	    bm->GetRunTimes()->stop(RunTimes::Solving);
	    if(!newS.okay())
	      {
		return false;
	      }
	    count = 0;
	    flag  = 1;
    	bm->GetRunTimes()->start(RunTimes::SendingToSAT);
	  }
        if (newS.okay())
          {
        	continue;
          }
        else
          {
            bm->PrintStats(newS);
            bm->GetRunTimes()->stop(RunTimes::SendingToSAT);
            return false;
          }
      } // End of For-loop adding the clauses

    bm->GetRunTimes()->stop(RunTimes::SendingToSAT);
    //cout << "Added remaining clauses\n";
    bm->GetRunTimes()->start(RunTimes::Solving);
    newS.solve();
    bm->GetRunTimes()->stop(RunTimes::Solving);
    bm->PrintStats(newS);
    if (newS.okay())
      return true;
    else
      return false;
  } //end of toSATandSolve()

  // Looks up truth value of ASTNode SYMBOL in MINISAT satisfying
  // assignment.
  ASTNode ToSAT::SymbolTruthValue(MINISAT::Solver &newS, ASTNode form)
  {
    MINISAT::Var satvar = _ASTNode_to_SATVar_Map[form];
    if (newS.model[satvar] == MINISAT::l_False)
      {
        return ASTFalse;
      }
    else
      {
        // True or undefined.
        return ASTTrue;
      }
  }

  // This function is for debugging problems with BitBlast and
  // especially ToCNF. It evaluates the bit-blasted formula in the
  // satisfying assignment.  While doing that, it checks that every
  // subformula has the same truth value as its representative
  // literal, if it has one.  If this condition is violated, it halts
  // immediately (on the leftmost lowest term).  Use CreateSimpForm to
  // evaluate, even though it's expensive, so that we can use the
  // partial truth assignment.
  ASTNode ToSAT::CheckBBandCNF(MINISAT::Solver& newS, ASTNode form)
  {
    // Clear memo table (in case newS has changed).
    CheckBBandCNFMemo.clear();
    // Call recursive version that does the work.
    return CheckBBandCNF_int(newS, form);
  } //End of CheckBBandCNF()

  // Recursive body CheckBBandCNF
  ASTNode ToSAT::CheckBBandCNF_int(MINISAT::Solver& newS, ASTNode form)
  {
    //     cout << "++++++++++++++++"
    // 	 << endl
    // 	 << "CheckBBandCNF_int form = "
    // 	 << form << endl;

    ASTNodeMap::iterator memoit = CheckBBandCNFMemo.find(form);
    if (memoit != CheckBBandCNFMemo.end())
      {
        // found it.  Return memoized value.
        return memoit->second;
      }

    ASTNode result; // return value, to memoize.

    Kind k = form.GetKind();
    switch (k)
      {
      case TRUE:
      case FALSE:
        {
          return form;
          break;
        }
      case SYMBOL:
      case BVGETBIT:
        {
          result = SymbolTruthValue(newS, form);

	  //           cout << "================"
	  //                << endl
	  //                << "Checking BB formula:"
	  //                << form << endl;
	  //           cout << "----------------"
	  //                << endl
	  //                << "Result:" << result << endl;
          break;
        }
      default:
        {
          // Evaluate the children recursively.
          ASTVec eval_children;
          ASTVec ch = form.GetChildren();
          ASTVec::iterator itend = ch.end();
          for (ASTVec::iterator it = ch.begin(); it < itend; it++)
            {
              eval_children.push_back(CheckBBandCNF_int(newS, *it));
            }
          result = bm->CreateSimpForm(k, eval_children);

	  //           cout << "================"
	  //                << endl
	  //                << "Checking BB formula:" << form << endl;
	  //           cout << "----------------"
	  //                << endl
	  //                << "Result:" << result << endl;

          ASTNode replit_eval;
          // Compare with replit, if there is one.
          ASTNodeMap::iterator replit_it = RepLitMap.find(form);
          if (replit_it != RepLitMap.end())
            {
              ASTNode replit = RepLitMap[form];
              // Replit is symbol or not symbol.
              if (SYMBOL == replit.GetKind())
                {
                  replit_eval = SymbolTruthValue(newS, replit);
                }
              else
                {
                  // It's (NOT sym).  Get value of sym and complement.
                  replit_eval =
                    bm->CreateSimpNot(SymbolTruthValue(newS, replit[0]));
                }

	      //               cout << "----------------"
	      //                    << endl
	      //                    << "Rep lit: " << replit << endl;
	      //               cout << "----------------"
	      //                    << endl
	      //                    << "Rep lit value: " << replit_eval << endl;

              if (result != replit_eval)
                {
                  // Hit the panic button.
                  FatalError("Truth value of BitBlasted formula "\
                             "disagrees with representative literal in CNF.");
                }
            }
          else
            {
              //cout << "----------------" << endl << "No rep lit" << endl;
            }

        }
      }

    return (CheckBBandCNFMemo[form] = result);
  } //end of CheckBBandCNF_int()
}; //end of namespace BEEV
<|endoftext|>


<commit_before>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <math.h>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <fstream>
#include <votca/csg/csgapplication.h>
#include <votca/csg/trajectorywriter.h>

using namespace std;
using namespace votca::csg;

class CsgMapApp
    : public CsgApplication
{
public:
    string ProgramName() { return "csg_map"; }
    void HelpText(ostream &out) {
      out << "Convert a reference atomistic trajectory or configuration into a coarse-grained one \n"
          << "based on a mapping xml-file. The mapping can be applied to either an entire trajectory \n"
          << "or a selected set of frames only (see options). The conventional file extensions of \n"
	  << "the supported simulation engines, e.g. Gromacs, are recognized. In the case of DL_POLY \n"
          << "the following convention is adopted: <name>.dlpf, <name>.dlpc and <name>.dlph  must \n"
	  << "be used for topology, configuration and trajectory files (aka FIELD, CONFIG and HISTORY). \n"
	  << "Moreover, by convention, <name> can be omitted, i.e. stand-alone extensions can be used, \n"
	  << "which invoke the corresponding standard names: FIELD, CONFIG, HISTORY (in the input), \n"
	  << "or FIELD_CGV, CONFIG_CGV, HISTORY_CGV (in the output). \n"
	  << "- NOTE: the tool can also be used for cross-converting configuration or trajectory files \n"
	  << "between the formats of the supported simulation engines!\n\n"
	  << "Examples:\n"
	  << "* csg_map --top FA-gromacs.tpr --trj FA-gromacs.trr --out CG-gromacs.xtc --cg cg-map.xml\n"
	  << "  - convert FA-gromacs.trr to CG-gromacs.xtc (trajectory in Gromacs format)\n"
	  << "* csg_map --top FA-gromacs.tpr --trj FA-gromacs.gro --out CG-gromacs.gro --cg cg-map.xml\n"
	  << "  - convert FA-gromacs.gro to CG-gromacs.gro (configuration in Gromacs format)\n"
	  << "* csg_map --top FA-dlpoly.dlpf --trj FA-dlpoly.dlph --out CG-dlpoly.dlph --cg cg-map.xml\n"
	  << "  - convert FA-dlpoly.dlph to CG-dlpoly.dlph (trajectory in DL_POLY format)\n"
	  << "* csg_map --top FA-gromacs.tpr --trj FA-gromacs.gro --out CG-dlpoly.dlpc --no-map\n"
	  << "  - convert FA-gromacs.gro to CG-dlpoly.dlpc (configuration: Gromacs to DL_POLY format)\n"
	  << "* csg_map --top .dlpf --trj .dlph --out .dlph --cg cg-map.xml --nframes 100\n"
	  << "  - convert HISTORY to HISTORY_CGV (trajectory in DL_POLY format: 100 frames only)\n";
    }

    bool DoTrajectory() { return true;}
    bool DoMapping() { return true;}

    void Initialize() {
        CsgApplication::Initialize();
        AddProgramOptions()
	  ("out", boost::program_options::value<string>(),
           "  output file for coarse-grained trajectory; examples:\n"
           "  - <name>.trr, <name>.xtc, <name>.gro (Gromacs),\n"
           "  - <name>.dlph, <name>.dlpc, .dlph, .dlpc (DL_POLY)\n  ('.dlph'='use HISTORY_CGV', '.dlpc'='use CONFIG_CGV')")
	  ("vel", "  Write mapped velocities (if available)")
	  ("hybrid", "  Create hybrid trajectory containing both atomistic and coarse-grained");
    }

    bool EvaluateOptions() {
        CsgApplication::EvaluateOptions();
        CheckRequired("trj", "no trajectory file specified");
        CheckRequired("out", "need to specify output trajectory");
        return true;
    }

    void BeginEvaluate(Topology *top, Topology *top_ref);
void EvalConfiguration(Topology *top, Topology *top_ref) {
        if (!_do_hybrid) {
            // simply write the topology mapped by csgapplication class
            if (_do_vel) top->SetHasVel(true);
            _writer->Write(top);
        } else {
            // we want to combine atomistic and coarse-grained into one topology
            Topology *hybtol = new Topology();

            BeadContainer::iterator it_bead;
            ResidueContainer::iterator it_res;
            MoleculeContainer::iterator it_mol;
            InteractionContainer::iterator it_ia;

            hybtol->setBox(top->getBox());
            hybtol->setTime(top->getTime());
            hybtol->setStep(top->getStep());

            // copy all residues from both
            for (it_res = top_ref->Residues().begin(); it_res != top_ref->Residues().end(); ++it_res) {
                hybtol->CreateResidue((*it_res)->getName());
            }
            for (it_res = top->Residues().begin(); it_res != top->Residues().end(); ++it_res) {
                hybtol->CreateResidue((*it_res)->getName());
            }

            // copy all molecules and beads

            for(it_mol=top_ref->Molecules().begin();it_mol!=top_ref->Molecules().end(); ++it_mol) {
                Molecule *mi = hybtol->CreateMolecule((*it_mol)->getName());
                for (int i = 0; i < (*it_mol)->BeadCount(); i++) {
                    // copy atomistic beads of molecule
                    int beadid = (*it_mol)->getBead(i)->getId();

                    Bead *bi = (*it_mol)->getBead(i);
                    BeadType *type = hybtol->GetOrCreateBeadType(bi->getType()->getName());
                    Bead *bn = hybtol->CreateBead(bi->getSymmetry(), bi->getName(), type, bi->getResnr(), bi->getM(), bi->getQ());
                    bn->setOptions(bi->Options());
                    bn->setPos(bi->getPos());
                    if (bi->HasVel()) bn->setVel(bi->getVel());

                    mi->AddBead(hybtol->Beads()[beadid], (*it_mol)->getBeadName(i));

                }

                if (mi->getId() < top->MoleculeCount()) {
                    // copy cg beads of molecule
                    Molecule *cgmol = top->Molecules()[mi->getId()];
                    for (int i = 0; i < cgmol->BeadCount(); i++) {
                        Bead *bi = cgmol->getBead(i);
                        // todo: this is a bit dirty as a cg bead will always have the resid of its first parent
                        Bead *bparent = (*it_mol)->getBead(0);
                        BeadType *type = hybtol->GetOrCreateBeadType(bi->getType()->getName());
                        Bead *bn = hybtol->CreateBead(bi->getSymmetry(), bi->getName(), type, bparent->getResnr(), bi->getM(), bi->getQ());
                        bn->setOptions(bi->Options());
                        bn->setPos(bi->getPos());
                        if (bi->HasVel()) bn->setVel(bi->getVel());
                        int mid = bparent->getMolecule()->getId();
                        mi->AddBead(bi, bi->getName());
                    }
                }

            }
           hybtol->setBox(top_ref->getBox());

            _writer->Write(hybtol);
        }
    }

    void EndEvaluate() {
        _writer->Close();
        delete _writer;
    }

protected:
    TrajectoryWriter *_writer;
    bool _do_hybrid;
    bool _do_vel;

};

void CsgMapApp::BeginEvaluate(Topology *top, Topology *top_atom) {
    string out = OptionsMap()["out"].as<string > ();
    cout << "writing coarse-grained trajectory to " << out << endl;
    _writer = TrjWriterFactory().Create(out);
    if (_writer == NULL)
        throw runtime_error("output format not supported: " + out);

    _do_hybrid = false;
    if(OptionsMap().count("hybrid")){
        if (!_do_mapping)
            throw runtime_error("options hybrid and no-map not compatible");
        cout << "Doing hybrid mapping..." << endl;
        _do_hybrid = true;
    }

    _do_vel = false;
    if(OptionsMap().count("vel")){
        _do_vel = true;
    }

    _writer->Open(out);
};

int main(int argc, char **argv)
{
    CsgMapApp app;
    return app.Exec(argc, argv);
}

<commit_msg>csg_map: shorten help<commit_after>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <math.h>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <fstream>
#include <votca/csg/csgapplication.h>
#include <votca/csg/trajectorywriter.h>

using namespace std;
using namespace votca::csg;

class CsgMapApp
    : public CsgApplication
{
public:
    string ProgramName() { return "csg_map"; }
    void HelpText(ostream &out) {
      out << "Convert a reference atomistic trajectory or configuration into a coarse-grained one \n"
          << "based on a mapping xml-file. The mapping can be applied to either an entire trajectory \n"
          << "or a selected set of frames only (see options).\n"
	  << "Examples:\n"
	  << "* csg_map --top topol.tpr --trj traj.trr --out traj_cg.xtc --cg cg-map.xml\n"
	  << "* csg_map --top topol.tpr --trj conf.gro --out traj_cg.trr --cg cg-map.xml\n"
	  << "* csg_map --top dlpoly_field.dlpf --trj dlpoly.dlph --out CG-dlpoly.dlph --cg cg-map.xml\n"
	  << "* csg_map --top topol.tpr --trj conf.gro --out dlpoly.dlpc --no-map\n"
	  << "* csg_map --top .dlpf --trj .dlph --out .dlph --cg cg-map.xml  convert HISTORY to HISTORY_CGV\n";
    }

    bool DoTrajectory() { return true;}
    bool DoMapping() { return true;}

    void Initialize() {
        CsgApplication::Initialize();
        AddProgramOptions()
	  ("out", boost::program_options::value<string>(),"  output file for coarse-grained trajectory")
	  ("vel", "  Write mapped velocities (if available)")
	  ("hybrid", "  Create hybrid trajectory containing both atomistic and coarse-grained");
    }

    bool EvaluateOptions() {
        CsgApplication::EvaluateOptions();
        CheckRequired("trj", "no trajectory file specified");
        CheckRequired("out", "need to specify output trajectory");
        return true;
    }

    void BeginEvaluate(Topology *top, Topology *top_ref);
void EvalConfiguration(Topology *top, Topology *top_ref) {
        if (!_do_hybrid) {
            // simply write the topology mapped by csgapplication class
            if (_do_vel) top->SetHasVel(true);
            _writer->Write(top);
        } else {
            // we want to combine atomistic and coarse-grained into one topology
            Topology *hybtol = new Topology();

            BeadContainer::iterator it_bead;
            ResidueContainer::iterator it_res;
            MoleculeContainer::iterator it_mol;
            InteractionContainer::iterator it_ia;

            hybtol->setBox(top->getBox());
            hybtol->setTime(top->getTime());
            hybtol->setStep(top->getStep());

            // copy all residues from both
            for (it_res = top_ref->Residues().begin(); it_res != top_ref->Residues().end(); ++it_res) {
                hybtol->CreateResidue((*it_res)->getName());
            }
            for (it_res = top->Residues().begin(); it_res != top->Residues().end(); ++it_res) {
                hybtol->CreateResidue((*it_res)->getName());
            }

            // copy all molecules and beads

            for(it_mol=top_ref->Molecules().begin();it_mol!=top_ref->Molecules().end(); ++it_mol) {
                Molecule *mi = hybtol->CreateMolecule((*it_mol)->getName());
                for (int i = 0; i < (*it_mol)->BeadCount(); i++) {
                    // copy atomistic beads of molecule
                    int beadid = (*it_mol)->getBead(i)->getId();

                    Bead *bi = (*it_mol)->getBead(i);
                    BeadType *type = hybtol->GetOrCreateBeadType(bi->getType()->getName());
                    Bead *bn = hybtol->CreateBead(bi->getSymmetry(), bi->getName(), type, bi->getResnr(), bi->getM(), bi->getQ());
                    bn->setOptions(bi->Options());
                    bn->setPos(bi->getPos());
                    if (bi->HasVel()) bn->setVel(bi->getVel());

                    mi->AddBead(hybtol->Beads()[beadid], (*it_mol)->getBeadName(i));

                }

                if (mi->getId() < top->MoleculeCount()) {
                    // copy cg beads of molecule
                    Molecule *cgmol = top->Molecules()[mi->getId()];
                    for (int i = 0; i < cgmol->BeadCount(); i++) {
                        Bead *bi = cgmol->getBead(i);
                        // todo: this is a bit dirty as a cg bead will always have the resid of its first parent
                        Bead *bparent = (*it_mol)->getBead(0);
                        BeadType *type = hybtol->GetOrCreateBeadType(bi->getType()->getName());
                        Bead *bn = hybtol->CreateBead(bi->getSymmetry(), bi->getName(), type, bparent->getResnr(), bi->getM(), bi->getQ());
                        bn->setOptions(bi->Options());
                        bn->setPos(bi->getPos());
                        if (bi->HasVel()) bn->setVel(bi->getVel());
                        int mid = bparent->getMolecule()->getId();
                        mi->AddBead(bi, bi->getName());
                    }
                }

            }
           hybtol->setBox(top_ref->getBox());

            _writer->Write(hybtol);
        }
    }

    void EndEvaluate() {
        _writer->Close();
        delete _writer;
    }

protected:
    TrajectoryWriter *_writer;
    bool _do_hybrid;
    bool _do_vel;

};

void CsgMapApp::BeginEvaluate(Topology *top, Topology *top_atom) {
    string out = OptionsMap()["out"].as<string > ();
    cout << "writing coarse-grained trajectory to " << out << endl;
    _writer = TrjWriterFactory().Create(out);
    if (_writer == NULL)
        throw runtime_error("output format not supported: " + out);

    _do_hybrid = false;
    if(OptionsMap().count("hybrid")){
        if (!_do_mapping)
            throw runtime_error("options hybrid and no-map not compatible");
        cout << "Doing hybrid mapping..." << endl;
        _do_hybrid = true;
    }

    _do_vel = false;
    if(OptionsMap().count("vel")){
        _do_vel = true;
    }

    _writer->Open(out);
};

int main(int argc, char **argv)
{
    CsgMapApp app;
    return app.Exec(argc, argv);
}

<|endoftext|>


<commit_before>#include "polymer.h"

void Polymer::Initialize(){
    QMApplication::Initialize();
    /// define standard program options
    AddProgramOptions("Polymer options")
    ("cutnrg", boost::program_options::value<double>(), "wavefunctions will be considered only if their eigenvalues are greater than the smallest one by this amount");

}

bool Polymer::EvaluateOptions(){
    QMApplication::EvaluateOptions();
    CheckRequired("cutnrg", "no energy cutoff given");
    _cutnrg = OptionsMap()["cutnrg"].as<double>();
}

bool Polymer::EvaluateFrame(){
    UpdatePolTop();
    string outn ("frame");
    outn = outn + lexical_cast<string> (_qmtop.getStep());
    Save(outn);
    Clean();
}

void Polymer::EndEvaluate(){

}

void Polymer::UpdatePolTop(){
    // 1) compute "wavefunction" for each molecule
    MoleculeContainer::iterator itMol=_qmtop.Molecules().begin();

    for ( ; itMol!= _qmtop.Molecules().end(); ++itMol){
        CalcWaveFunction(*itMol);
    }

    // 2) create new neighbour list
    QMNBList &nblist = _qmtop.nblist();
    for(QMNBList::iterator iter = nblist.begin();iter!=nblist.end();++iter){
        CrgUnit * one = (*iter)->Crg1();
        CrgUnit * two = (*iter)->Crg2();
        //insert check for size of Js
        double J = ((*iter)->Js())[0];
        UpdateJs (one, two,J); // hard code that
                               // only one element is
                               // considered (otherwise
                               // the whole method is doubtful)
    }

    // 3) now that the new neighbour list is there, compute the dr.
    map<PairWF, double>::iterator itpwf=_polJs.begin();
    for(;itpwf != _polJs.end(); ++itpwf){
        UpdatedR(itpwf->first);
    }
}

void Polymer::UpdateJs(CrgUnit * one, CrgUnit *two, const double & J){

    int mol1 = one->getMolId();
    int mol2 = two->getMolId();
    if (mol1 == mol2) {
        return;
    }
    vector <WaveFunction *>::iterator it1=_mstates[mol1]->begin();
    vector <WaveFunction *>::iterator it2=_mstates[mol2]->begin();
    map<int, int>::iterator itm1;
    map<int, int>::iterator itm2;
    itm1=_mcrg2bs.find(one->getId());
    itm2=_mcrg2bs.find(two->getId());
    if (itm1 == _mcrg2bs.end() || itm2 == _mcrg2bs.end() ){
        throw runtime_error ("could not find the crgunit in the index in UpdateJs");
    }
    for ( ; it1 != _mstates[mol1]->end(); ++it1){
        for ( ; it2 != _mstates[mol2]->end(); ++it2){

            double dJ = gsl_vector_get( (*it1)->_wf,  itm1->second) *
                        gsl_vector_get( (*it2)->_wf,  itm2->second) * J;
            map < PairWF , double >::iterator
              itJ = _polJs.find( make_pair(*it1, *it2));
            if (itJ == _polJs.end()){
                _polJs.insert(make_pair (make_pair(*it1, *it2),dJ));
            }
            else {
                itJ->second += dJ;
            }

        }
    }
}

void Polymer::CalcWaveFunction(Molecule * mol){
    int nbeads = mol->BeadCount();
    static int id=0;
    gsl_matrix * pH = gsl_matrix_calloc( nbeads, nbeads);
    double Jmax = 0.5;
    vector <WaveFunction *> * melement = new vector < WaveFunction *> ;
    _mstates.push_back( melement);

    //1 set diagonal elements
    for (int i=0; i< nbeads;i++){
        CrgUnit * crg = dynamic_cast<QMBead*>(mol->getBead(i))
            ->GetCrgUnit();
        double nrg = crg->getEnergy();
        gsl_matrix_set (pH,i,i, nrg);
        // set a map from CrgUnits -> the integer associated with them
        map<int, int>::iterator itm = _mcrg2bs.find(crg->getId());
        if (itm == _mcrg2bs.end()){
            _mcrg2bs.insert(make_pair(crg->getId(), i));
        }
        else {
            throw runtime_error ("each crgunit should only appeare once in CalcWaveFunction");
        }
        QMBead* tbead = dynamic_cast<QMBead*>(mol->getBead(i));
        if (tbead->getiPos() != 0 ){
            throw runtime_error("each qmbead should have ipos correpsonding to its pos in the molecule");
        }
    }

    //2 set offdiagonal elements
    // in principle it would be nice to do this via the interactions
    // but this is not copied/written in statesaver

    //InteractionContainer::iterator itC=mol->Interactions().begin();
    //for ( ;itC != mol->Interactions.end(); itC++){
    //}
    for (int i=0;i<nbeads-1;i++){
        int j = i+1;
        vec one;
        vec two;
        one = mol->getBead(i)->getU();
        two = mol->getBead(j)->getU();
        // this will change using the reverse polish notation object.
        // dribble dribble
        double J = Jmax * (one * two);
        gsl_matrix_set(pH, i,j, J);
        gsl_matrix_set(pH, j,i, J);
    }

    gsl_eigen_symmv_workspace * gslwork = gsl_eigen_symmv_alloc(nbeads);
    gsl_vector *eval = gsl_vector_alloc (nbeads);
    gsl_matrix *evec = gsl_matrix_alloc (nbeads, nbeads);
    gsl_eigen_symmv(pH,eval, evec,gslwork);
    gsl_eigen_symmv_sort (eval, evec, GSL_EIGEN_SORT_VAL_ASC);

    //for each evector make a new wavefunction
    for (int i=0;i<nbeads;i++){
        if ( gsl_vector_get(eval,i) < gsl_vector_get(eval,0) + _cutnrg ){
            gsl_vector * pv = gsl_vector_alloc (nbeads);
            gsl_vector_memcpy(pv, &(gsl_matrix_column(evec, i).vector) );

            WaveFunction * wf = new WaveFunction;
            wf->_molid  = mol->getId();
            wf->_wfid = i;
            wf->_nrg = gsl_vector_get(eval,i);
            wf->_id = id;
            wf->_wf = pv;
            _states.push_back(wf);
            melement->push_back(wf);
            //determine the position
            wf->_pos=vec(0.,0.,0.);
            for (int j=0;j<nbeads;j++){
                wf->_pos += (gsl_vector_get(pv,j) * gsl_vector_get(pv,j)) *
                        (mol->getBead(j)->getPos());
            }
            id++;
        }
    }

    gsl_matrix_free(pH);
    gsl_matrix_free(evec);
    gsl_eigen_symmv_free(gslwork);
    gsl_vector_free(eval);

}

void Polymer::Save(string & outn){
    string outnrg = outn + string ("nrg.txt");
    ofstream  out;
    out.open(outnrg.c_str());
    vector <WaveFunction *>::iterator its = _states.begin();
    for (; its!=_states.end();its++ ){
        out << "mol id: " << (*its)->_molid
                << " wf id: " << (*its)->_wfid
                << " wf abs id: " << (*its)->_id
                << " energy " << (*its)->_nrg << '\n';
    }
    out << endl;
    out.close();

    string outneigh = outn + string ("neigh.txt");
    out.open(outneigh.c_str());
    map < PairWF, double> ::iterator itJ = _polJs.begin();
    map < PairWF, vec> ::iterator itR = _poldR.begin();
    for (; itJ!= _polJs.end(); ++itJ, ++itR){
        out << " wf ids: " << ((itJ->first).first)->_id <<
                " " << ((itJ->first).second)->_id <<
                " J " << (itJ->second) <<
                " dR " << (itR->second) <<'\n';
    }
    out.close();

}

void Polymer::Clean(){
    vector <WaveFunction *>::iterator its = _states.begin();
    for (; its!=_states.end();its++ ){
        gsl_vector_free((*its)->_wf);
        delete *its;
    }
    _states.clear();
    vector < vector < WaveFunction * > *>::iterator itms = _mstates.begin();
    for ( ; itms != _mstates.end(); ++itms){
        (*itms)->clear();
    }
    _mstates.clear();
    _polJs.clear();
    _poldR.clear();
    _mcrg2bs.clear();
}

void Polymer::UpdatedR(const PairWF & pwf){

    vec r1 = (pwf.first)->_pos;
    vec r2 =(pwf.second)->_pos;
    vec d = _qmtop.BCShortestConnection(r1, r2);
    _poldR.insert(make_pair(pwf, d));

}

int main(int argc, char** argv) {

    Polymer pol_calc;
    return pol_calc.Exec(argc, argv);
}
<commit_msg>polymer compiles<commit_after>#include "polymer.h"

void Polymer::Initialize(){
    QMApplication::Initialize();
    /// define standard program options
    AddProgramOptions("Polymer options")
    ("cutnrg", boost::program_options::value<double>(), "wavefunctions will be considered only if their eigenvalues are greater than the smallest one by this amount");

}

bool Polymer::EvaluateOptions(){
    QMApplication::EvaluateOptions();
    CheckRequired("cutnrg", "no energy cutoff given");
    _cutnrg = OptionsMap()["cutnrg"].as<double>();
}

bool Polymer::EvaluateFrame(){
    UpdatePolTop();
    string outn ("frame");
    outn = outn + lexical_cast<string> (_qmtop.getStep());
    Save(outn);
    Clean();
}

void Polymer::EndEvaluate(){

}

void Polymer::UpdatePolTop(){
    // 1) compute "wavefunction" for each molecule
    MoleculeContainer::iterator itMol=_qmtop.Molecules().begin();

    for ( ; itMol!= _qmtop.Molecules().end(); ++itMol){
        CalcWaveFunction(*itMol);
    }

    // 2) create new neighbour list
    QMNBList &nblist = _qmtop.nblist();
    for(QMNBList::iterator iter = nblist.begin();iter!=nblist.end();++iter){
        CrgUnit * one = (*iter)->Crg1();
        CrgUnit * two = (*iter)->Crg2();
        //insert check for size of Js
        double J = ((*iter)->Js())[0];
        UpdateJs (one, two,J); // hard code that
                               // only one element is
                               // considered (otherwise
                               // the whole method is doubtful)
    }

    // 3) now that the new neighbour list is there, compute the dr.
    map<PairWF, double>::iterator itpwf=_polJs.begin();
    for(;itpwf != _polJs.end(); ++itpwf){
        UpdatedR(itpwf->first);
    }
}

void Polymer::UpdateJs(CrgUnit * one, CrgUnit *two, const double & J){

    int mol1 = one->getMolId();
    int mol2 = two->getMolId();
    if (mol1 == mol2) {
        return;
    }
    vector <WaveFunction *>::iterator it1=_mstates[mol1]->begin();
    vector <WaveFunction *>::iterator it2=_mstates[mol2]->begin();
    map<int, int>::iterator itm1;
    map<int, int>::iterator itm2;
    itm1=_mcrg2bs.find(one->getId());
    itm2=_mcrg2bs.find(two->getId());
    if (itm1 == _mcrg2bs.end() || itm2 == _mcrg2bs.end() ){
        throw runtime_error ("could not find the crgunit in the index in UpdateJs");
    }
    for ( ; it1 != _mstates[mol1]->end(); ++it1){
        for ( ; it2 != _mstates[mol2]->end(); ++it2){

            double dJ = gsl_vector_get( (*it1)->_wf,  itm1->second) *
                        gsl_vector_get( (*it2)->_wf,  itm2->second) * J;
            map < PairWF , double >::iterator
              itJ = _polJs.find( make_pair(*it1, *it2));
            if (itJ == _polJs.end()){
                _polJs.insert(make_pair (make_pair(*it1, *it2),dJ));
            }
            else {
                itJ->second += dJ;
            }

        }
    }
}

void Polymer::CalcWaveFunction(Molecule * mol){
    int nbeads = mol->BeadCount();
    static int id=0;
    gsl_matrix * pH = gsl_matrix_calloc( nbeads, nbeads);
    double Jmax = 0.5;
    vector <WaveFunction *> * melement = new vector < WaveFunction *> ;
    _mstates.push_back( melement);

    //1 set diagonal elements
    for (int i=0; i< nbeads;i++){
        QMCrgUnit * crg = dynamic_cast<QMBead*>(mol->getBead(i))
            ->GetCrgUnit();
		double nrg = crg->getTotalEnergy();
        gsl_matrix_set (pH,i,i, nrg);
        // set a map from CrgUnits -> the integer associated with them
        map<int, int>::iterator itm = _mcrg2bs.find(crg->getId());
        if (itm == _mcrg2bs.end()){
            _mcrg2bs.insert(make_pair(crg->getId(), i));
        }
        else {
            throw runtime_error ("each crgunit should only appeare once in CalcWaveFunction");
        }
        QMBead* tbead = dynamic_cast<QMBead*>(mol->getBead(i));
        if (tbead->getiPos() != 0 ){
            throw runtime_error("each qmbead should have ipos correpsonding to its pos in the molecule");
        }
    }

    //2 set offdiagonal elements
    // in principle it would be nice to do this via the interactions
    // but this is not copied/written in statesaver

    //InteractionContainer::iterator itC=mol->Interactions().begin();
    //for ( ;itC != mol->Interactions.end(); itC++){
    //}
    for (int i=0;i<nbeads-1;i++){
        int j = i+1;
        vec one;
        vec two;
        one = mol->getBead(i)->getU();
        two = mol->getBead(j)->getU();
        // this will change using the reverse polish notation object.
        // dribble dribble
        double J = Jmax * (one * two);
        gsl_matrix_set(pH, i,j, J);
        gsl_matrix_set(pH, j,i, J);
    }

    gsl_eigen_symmv_workspace * gslwork = gsl_eigen_symmv_alloc(nbeads);
    gsl_vector *eval = gsl_vector_alloc (nbeads);
    gsl_matrix *evec = gsl_matrix_alloc (nbeads, nbeads);
    gsl_eigen_symmv(pH,eval, evec,gslwork);
    gsl_eigen_symmv_sort (eval, evec, GSL_EIGEN_SORT_VAL_ASC);

    //for each evector make a new wavefunction
    for (int i=0;i<nbeads;i++){
        if ( gsl_vector_get(eval,i) < gsl_vector_get(eval,0) + _cutnrg ){
            gsl_vector * pv = gsl_vector_alloc (nbeads);
            gsl_vector_memcpy(pv, &(gsl_matrix_column(evec, i).vector) );

            WaveFunction * wf = new WaveFunction;
            wf->_molid  = mol->getId();
            wf->_wfid = i;
            wf->_nrg = gsl_vector_get(eval,i);
            wf->_id = id;
            wf->_wf = pv;
            _states.push_back(wf);
            melement->push_back(wf);
            //determine the position
            wf->_pos=vec(0.,0.,0.);
            for (int j=0;j<nbeads;j++){
                wf->_pos += (gsl_vector_get(pv,j) * gsl_vector_get(pv,j)) *
                        (mol->getBead(j)->getPos());
            }
            id++;
        }
    }

    gsl_matrix_free(pH);
    gsl_matrix_free(evec);
    gsl_eigen_symmv_free(gslwork);
    gsl_vector_free(eval);

}

void Polymer::Save(string & outn){
    string outnrg = outn + string ("nrg.txt");
    ofstream  out;
    out.open(outnrg.c_str());
    vector <WaveFunction *>::iterator its = _states.begin();
    for (; its!=_states.end();its++ ){
        out << "mol id: " << (*its)->_molid
                << " wf id: " << (*its)->_wfid
                << " wf abs id: " << (*its)->_id
                << " energy " << (*its)->_nrg << '\n';
    }
    out << endl;
    out.close();

    string outneigh = outn + string ("neigh.txt");
    out.open(outneigh.c_str());
    map < PairWF, double> ::iterator itJ = _polJs.begin();
    map < PairWF, vec> ::iterator itR = _poldR.begin();
    for (; itJ!= _polJs.end(); ++itJ, ++itR){
        out << " wf ids: " << ((itJ->first).first)->_id <<
                " " << ((itJ->first).second)->_id <<
                " J " << (itJ->second) <<
                " dR " << (itR->second) <<'\n';
    }
    out.close();

}

void Polymer::Clean(){
    vector <WaveFunction *>::iterator its = _states.begin();
    for (; its!=_states.end();its++ ){
        gsl_vector_free((*its)->_wf);
        delete *its;
    }
    _states.clear();
    vector < vector < WaveFunction * > *>::iterator itms = _mstates.begin();
    for ( ; itms != _mstates.end(); ++itms){
        (*itms)->clear();
    }
    _mstates.clear();
    _polJs.clear();
    _poldR.clear();
    _mcrg2bs.clear();
}

void Polymer::UpdatedR(const PairWF & pwf){

    vec r1 = (pwf.first)->_pos;
    vec r2 =(pwf.second)->_pos;
    vec d = _qmtop.BCShortestConnection(r1, r2);
    _poldR.insert(make_pair(pwf, d));

}

int main(int argc, char** argv) {

    Polymer pol_calc;
    return pol_calc.Exec(argc, argv);
}
<|endoftext|>


<commit_before>#ifndef HWCSCSPMV_HPP
#define HWCSCSPMV_HPP

#include <vector>
#include <string>

#include "cscspmv.hpp"
#include "wrapperregdriver.h"
#include "commonsemirings.hpp"

// implements the exec() for software-based SpMV-over-semirings
// add() and mul() must be implemented in the derived class

// TODO better control of acc-host buffer duplication in sw drivers --
// right now there are two copies of all (host+accel) and coherency mvs.
// are automatically called every time

template <class SpMVInd, class SpMVVal>
class HWSpMV : public virtual CSCSpMV<SpMVInd, SpMVVal>, public AddMulSemiring<SpMVInd, SpMVVal> {
protected:
  using CSCSpMV<SpMVInd, SpMVVal>::m_A;
  using CSCSpMV<SpMVInd, SpMVVal>::m_y;
  using CSCSpMV<SpMVInd, SpMVVal>::m_x;

  WrapperRegDriver * m_platform;
  const char * m_attachName;
  AccelReg readReg(unsigned int i) {return m_platform->readReg(i);}
  void writeReg(unsigned int i, AccelReg v) {m_platform->writeReg(i,v);}

  // register access functions -- copied from the TidbitsPlatformWrapper-generated driver
  // note that these will change if the SpMV accelerator interface is modified!
  AccelReg get_signature() {return readReg(0);}
  void set_start(AccelReg value) {writeReg(1, value);}
  void set_mode(AccelReg value) {writeReg(2, value);}
  AccelReg get_finished() {return readReg(3);}
  void set_csc_colPtr(AccelDblReg value) { writeReg(4, (AccelReg)(value >> 32)); writeReg(5, (AccelReg)(value & 0xffffffff)); }
  void set_csc_rowInd(AccelDblReg value) { writeReg(6, (AccelReg)(value >> 32)); writeReg(7, (AccelReg)(value & 0xffffffff)); }
  void set_csc_nzData(AccelDblReg value) { writeReg(8, (AccelReg)(value >> 32)); writeReg(9, (AccelReg)(value & 0xffffffff)); }
  void set_csc_inpVec(AccelDblReg value) { writeReg(10, (AccelReg)(value >> 32)); writeReg(11, (AccelReg)(value & 0xffffffff)); }
  void set_csc_outVec(AccelDblReg value) { writeReg(12, (AccelReg)(value >> 32)); writeReg(13, (AccelReg)(value & 0xffffffff)); }
  void set_csc_rows(AccelReg value) {writeReg(14, value);}
  void set_csc_cols(AccelReg value) {writeReg(15, value);}
  void set_csc_nz(AccelReg value) {writeReg(16, value);}

  // accelerator-side versions of SpMV data
  SpMVInd * m_acc_indPtrs;
  SpMVInd * m_acc_inds;
  SpMVVal * m_acc_nzData;
  SpMVVal * m_acc_x;
  SpMVVal * m_acc_y;
  unsigned int m_indPtrSize;
  unsigned int m_indSize;
  unsigned int m_nzDataSize;
  unsigned int m_xSize;
  unsigned int m_ySize;

  // mode settings for Seyrek
  typedef enum {
    START_REGULAR = 0,
    START_INIT = 1,
    START_FLUSH = 2
  } SeyrekModes;

  void execAccelMode(SeyrekModes mode) {
    // TODO ensure finished before starting new commands!
    set_mode(mode);
    set_start(1);
    // TODO add timeout option here?
    while(get_finished() != 1);
    set_start(0);
  }

public:
  HWSpMV(const char * attachName, WrapperRegDriver * driver) {
    m_platform = driver;
    m_attachName = attachName;
    m_platform->attach(attachName);
    m_acc_indPtrs = 0;
    m_acc_inds = 0;
    m_acc_nzData = 0;
    m_acc_x = 0;
    m_acc_y = 0;
    m_indPtrSize = 0;
    m_indSize = 0;
    m_nzDataSize = 0;
    m_xSize = 0;
    m_ySize = 0;
  }
  virtual ~HWSpMV() {m_platform->detach();}

  virtual void setA(CSC<SpMVInd, SpMVVal> * A) {
    // free the old accel buffers first, if alloc'd
    if(m_acc_indPtrs != 0) {
      m_platform->deallocAccelBuffer((void *) m_acc_indPtrs);
      m_platform->deallocAccelBuffer((void *) m_acc_inds);
      m_platform->deallocAccelBuffer((void *) m_acc_nzData);
    }
    if(m_acc_x) m_platform->deallocAccelBuffer((void *) m_acc_x);
    if(m_acc_y) m_platform->deallocAccelBuffer((void *) m_acc_y);
    // call base class impl
    CSCSpMV<SpMVInd, SpMVVal>::setA(A);
    // calculate the associated buffer sizes
    m_indPtrSize = sizeof(SpMVInd) * (m_A->getCols() + 1);
    m_indSize = sizeof(SpMVInd) * m_A->getNNZ();
    m_nzDataSize = sizeof(SpMVVal) * m_A->getNNZ();
    m_xSize = sizeof(SpMVVal) * m_A->getCols();
    m_ySize = sizeof(SpMVVal) * m_A->getRows();
    // alloc new accel buffers
    m_acc_indPtrs = (SpMVInd *) m_platform->allocAccelBuffer(m_indPtrSize);
    m_acc_inds = (SpMVInd *) m_platform->allocAccelBuffer(m_indSize);
    m_acc_nzData = (SpMVVal *) m_platform->allocAccelBuffer(m_nzDataSize);
    m_acc_x = (SpMVVal *) m_platform->allocAccelBuffer(m_xSize);
    m_acc_y = (SpMVVal *) m_platform->allocAccelBuffer(m_ySize);
    // copy matrix data host -> accel
    m_platform->copyBufferHostToAccel((void *)m_A->getIndPtrs(), (void *) m_acc_indPtrs, m_indPtrSize);
    m_platform->copyBufferHostToAccel((void *)m_A->getInds(), (void *) m_acc_inds, m_indSize);
    m_platform->copyBufferHostToAccel((void *)m_A->getNZData(), (void *) m_acc_nzData, m_nzDataSize);
    // set up matrix metadata in the accelerator
    set_csc_colPtr((AccelDblReg) m_acc_indPtrs);
    set_csc_cols(m_A->getCols());
    set_csc_inpVec((AccelDblReg) m_acc_x);
    set_csc_nz(m_A->getNNZ());
    set_csc_nzData((AccelDblReg) m_acc_nzData);
    set_csc_outVec((AccelDblReg) m_acc_y);
    set_csc_rowInd((AccelDblReg) m_acc_inds);
    set_csc_rows(m_A->getRows());
  }

  virtual void setx(SpMVVal * x) {
    // call base class impl
    CSCSpMV<SpMVInd, SpMVVal>::setx(x);
    // copy data
    m_platform->copyBufferHostToAccel((void *)x, (void *)m_acc_x, m_xSize);
  }

  virtual void sety(SpMVVal * y) {
    // call base class impl
    CSCSpMV<SpMVInd, SpMVVal>::sety(y);
    // copy data host -> accel
    m_platform->copyBufferHostToAccel((void *)y, (void *)m_acc_y, m_ySize);
  }

  virtual bool exec() {
    if(!m_A || !m_x || !m_y) throw "One or more SpMV data comps not assigned";
    // make sure x and y are up to date on the accel
    setx(m_x);
    sety(m_y);
    // TODO may not be always needed to do init and flush
    execAccelMode(START_INIT);
    execAccelMode(START_REGULAR);
    execAccelMode(START_FLUSH);
    // copy back y data to the host side
    m_platform->copyBufferAccelToHost((void *)m_acc_y, (void *)m_y, m_ySize);
    return true;
  }

  // TODO expose proper stats
  virtual unsigned int statInt(std::string name) { return 0;}

  virtual std::vector<std::string> statKeys() {
    std::vector<std::string> keys;
    keys.push_back("matrix");
  }
};

#endif // HWCSCSPMV_HPP
<commit_msg>support adding a base offset to reg accesses in HWCSCSpMV driver<commit_after>#ifndef HWCSCSPMV_HPP
#define HWCSCSPMV_HPP

#include <vector>
#include <string>

#include "cscspmv.hpp"
#include "wrapperregdriver.h"
#include "commonsemirings.hpp"

// number of registers per SpMV PE
#define HWSPMVPE_REGS   16

// TODO better control of acc-host buffer duplication in sw drivers --
// right now there are two copies of all (host+accel) and coherency mvs.
// are automatically called every time

template <class SpMVInd, class SpMVVal>
class HWSpMV : public virtual CSCSpMV<SpMVInd, SpMVVal>, public AddMulSemiring<SpMVInd, SpMVVal> {
protected:
  using CSCSpMV<SpMVInd, SpMVVal>::m_A;
  using CSCSpMV<SpMVInd, SpMVVal>::m_y;
  using CSCSpMV<SpMVInd, SpMVVal>::m_x;

  WrapperRegDriver * m_platform;
  const char * m_attachName;
  unsigned int m_peNum;

  // register offsets for the HW SpMV control/status registers
  // note that these may change if the SpMV accelerator interface is modified in Chisel!
  typedef enum {
    offsStart       = 1,
    offsMode        = 2,
    offsFinished    = 3,
    offsColPtrHi    = 4,
    offsColPtrLo    = 5,
    offsRowIndHi    = 6,
    offsRowIndLo    = 7,
    offsNzDatHi     = 8,
    offsNzDatLo     = 9,
    offsInpVecHi    = 10,
    offsInpVecLo    = 11,
    offsOutVecHi    = 12,
    offsOutVecLo    = 13,
    offsRows        = 14,
    offsCols        = 15,
    offsNZ          = 16
  } HWSpMVReg;
  // readReg and writeReg use peNum to add a base offset to the desired register ID
  AccelReg readReg(HWSpMVReg reg) {return m_platform->readReg(m_peNum * HWSPMVPE_REGS + reg);}
  void writeReg(HWSpMVReg reg, AccelReg v) {m_platform->writeReg(m_peNum * HWSPMVPE_REGS + reg, v);}
  // register accessor functions for this PE
  AccelReg get_signature() {return m_platform->readReg(0);} // signature is always at reg 0 (one for the entire accelerator)
  void set_start(AccelReg value) {writeReg(offsStart, value);}
  void set_mode(AccelReg value) {writeReg(offsMode, value);}
  AccelReg get_finished() {return readReg(offsFinished);}
  void set_csc_colPtr(AccelDblReg value) { writeReg(offsColPtrHi, (AccelReg)(value >> 32)); writeReg(offsColPtrLo, (AccelReg)(value & 0xffffffff)); }
  void set_csc_rowInd(AccelDblReg value) { writeReg(offsRowIndHi, (AccelReg)(value >> 32)); writeReg(offsRowIndLo, (AccelReg)(value & 0xffffffff)); }
  void set_csc_nzData(AccelDblReg value) { writeReg(offsNzDatHi, (AccelReg)(value >> 32)); writeReg(offsNzDatLo, (AccelReg)(value & 0xffffffff)); }
  void set_csc_inpVec(AccelDblReg value) { writeReg(offsInpVecHi, (AccelReg)(value >> 32)); writeReg(offsInpVecLo, (AccelReg)(value & 0xffffffff)); }
  void set_csc_outVec(AccelDblReg value) { writeReg(offsOutVecHi, (AccelReg)(value >> 32)); writeReg(offsOutVecLo, (AccelReg)(value & 0xffffffff)); }
  void set_csc_rows(AccelReg value) {writeReg(offsRows, value);}
  void set_csc_cols(AccelReg value) {writeReg(offsCols, value);}
  void set_csc_nz(AccelReg value) {writeReg(offsNZ, value);}

  // accelerator-side versions of SpMV data
  SpMVInd * m_acc_indPtrs;
  SpMVInd * m_acc_inds;
  SpMVVal * m_acc_nzData;
  SpMVVal * m_acc_x;
  SpMVVal * m_acc_y;
  unsigned int m_indPtrSize;
  unsigned int m_indSize;
  unsigned int m_nzDataSize;
  unsigned int m_xSize;
  unsigned int m_ySize;

  // mode settings for Seyrek
  typedef enum {
    START_REGULAR = 0,
    START_INIT = 1,
    START_FLUSH = 2
  } SeyrekModes;

  void execAccelMode(SeyrekModes mode) {
    // TODO ensure finished before starting new commands!
    set_mode(mode);
    set_start(1);
    // TODO add timeout option here?
    while(get_finished() != 1);
    set_start(0);
  }

public:
  HWSpMV(const char * attachName, WrapperRegDriver * driver, unsigned int peNum = 0) {
    m_platform = driver;
    m_attachName = attachName;
    m_platform->attach(attachName);
    m_acc_indPtrs = 0;
    m_acc_inds = 0;
    m_acc_nzData = 0;
    m_acc_x = 0;
    m_acc_y = 0;
    m_indPtrSize = 0;
    m_indSize = 0;
    m_nzDataSize = 0;
    m_xSize = 0;
    m_ySize = 0;
    m_peNum = peNum;
  }
  virtual ~HWSpMV() {m_platform->detach();}

  virtual void setA(CSC<SpMVInd, SpMVVal> * A) {
    // free the old accel buffers first, if alloc'd
    if(m_acc_indPtrs != 0) {
      m_platform->deallocAccelBuffer((void *) m_acc_indPtrs);
      m_platform->deallocAccelBuffer((void *) m_acc_inds);
      m_platform->deallocAccelBuffer((void *) m_acc_nzData);
    }
    if(m_acc_x) m_platform->deallocAccelBuffer((void *) m_acc_x);
    if(m_acc_y) m_platform->deallocAccelBuffer((void *) m_acc_y);
    // call base class impl
    CSCSpMV<SpMVInd, SpMVVal>::setA(A);
    // calculate the associated buffer sizes
    m_indPtrSize = sizeof(SpMVInd) * (m_A->getCols() + 1);
    m_indSize = sizeof(SpMVInd) * m_A->getNNZ();
    m_nzDataSize = sizeof(SpMVVal) * m_A->getNNZ();
    m_xSize = sizeof(SpMVVal) * m_A->getCols();
    m_ySize = sizeof(SpMVVal) * m_A->getRows();
    // alloc new accel buffers
    m_acc_indPtrs = (SpMVInd *) m_platform->allocAccelBuffer(m_indPtrSize);
    m_acc_inds = (SpMVInd *) m_platform->allocAccelBuffer(m_indSize);
    m_acc_nzData = (SpMVVal *) m_platform->allocAccelBuffer(m_nzDataSize);
    m_acc_x = (SpMVVal *) m_platform->allocAccelBuffer(m_xSize);
    m_acc_y = (SpMVVal *) m_platform->allocAccelBuffer(m_ySize);
    // copy matrix data host -> accel
    m_platform->copyBufferHostToAccel((void *)m_A->getIndPtrs(), (void *) m_acc_indPtrs, m_indPtrSize);
    m_platform->copyBufferHostToAccel((void *)m_A->getInds(), (void *) m_acc_inds, m_indSize);
    m_platform->copyBufferHostToAccel((void *)m_A->getNZData(), (void *) m_acc_nzData, m_nzDataSize);
    // set up matrix metadata in the accelerator
    set_csc_colPtr((AccelDblReg) m_acc_indPtrs);
    set_csc_cols(m_A->getCols());
    set_csc_inpVec((AccelDblReg) m_acc_x);
    set_csc_nz(m_A->getNNZ());
    set_csc_nzData((AccelDblReg) m_acc_nzData);
    set_csc_outVec((AccelDblReg) m_acc_y);
    set_csc_rowInd((AccelDblReg) m_acc_inds);
    set_csc_rows(m_A->getRows());
  }

  virtual void setx(SpMVVal * x) {
    // call base class impl
    CSCSpMV<SpMVInd, SpMVVal>::setx(x);
    // copy data
    m_platform->copyBufferHostToAccel((void *)x, (void *)m_acc_x, m_xSize);
  }

  virtual void sety(SpMVVal * y) {
    // call base class impl
    CSCSpMV<SpMVInd, SpMVVal>::sety(y);
    // copy data host -> accel
    m_platform->copyBufferHostToAccel((void *)y, (void *)m_acc_y, m_ySize);
  }

  virtual bool exec() {
    if(!m_A || !m_x || !m_y) throw "One or more SpMV data comps not assigned";
    // make sure x and y are up to date on the accel
    setx(m_x);
    sety(m_y);
    // TODO may not be always needed to do init and flush
    execAccelMode(START_INIT);
    execAccelMode(START_REGULAR);
    execAccelMode(START_FLUSH);
    // copy back y data to the host side
    m_platform->copyBufferAccelToHost((void *)m_acc_y, (void *)m_y, m_ySize);
    return true;
  }

  // TODO expose proper stats
  virtual unsigned int statInt(std::string name) { return 0;}

  virtual std::vector<std::string> statKeys() {
    std::vector<std::string> keys;
    keys.push_back("matrix");
  }
};

#endif // HWCSCSPMV_HPP
<|endoftext|>


<commit_before>/*
    Copyright 2008 Brain Research Institute, Melbourne, Australia

    Written by J-Donald Tournier, 27/06/08.

    This file is part of MRtrix.

    MRtrix is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MRtrix is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <gsl/gsl_blas.h>
#include <gsl/gsl_multimin.h>

#include "command.h"
#include "progressbar.h"
#include "math/vector.h"
#include "math/matrix.h"
#include "math/rng.h"
#include "dwi/directions/file.h"

using namespace MR;
using namespace App;

void usage () {

DESCRIPTION
  + "generate a set of uniformly distributed directions using a bipolar electrostatic repulsion model.";

REFERENCES
  + "* Jones, D.; Horsfield, M. & Simmons, A. "
  "Optimal strategies for measuring diffusion in anisotropic systems by magnetic resonance imaging. "
  "Magnetic Resonance in Medicine, 42: 515-525 (1999)."

  + "* Papadakis, N. G.; Murrills, C. D.; Hall, L. D.; Huang, C. L.-H. & Adrian Carpenter, T. "
  "Minimal gradient encoding for robust estimation of diffusion anisotropy. "
  "Magnetic Resonance Imaging, 18: 671-679 (2000).";

ARGUMENTS
  + Argument ("ndir", "the number of directions to generate.").type_integer (6, 60, std::numeric_limits<int>::max())
  + Argument ("dirs", "the text file to write the directions to, as [ az el ] pairs.").type_file_out();

OPTIONS
  + Option ("power", "specify exponent to use for repulsion power law (default: 2).")
  + Argument ("exp").type_integer (2, 2, std::numeric_limits<int>::max())

  + Option ("niter", "specify the maximum number of iterations to perform (default: 10000).")
  + Argument ("num").type_integer (1, 10000, std::numeric_limits<int>::max())

  + Option ("unipolar", "optimise assuming a unipolar electrostatic repulsion model rather than the bipolar model normally assumed in DWI")

  + Option ("cartesian", "Output the directions in Cartesian coordinates [x y z] instead of [az el].");

}

namespace
{
  double power = -1.0;
  size_t   ndirs = 0;
  bool bipolar = true;
}

class SinCos
{
  protected:
    double cos_az, sin_az, cos_el, sin_el;
    double r2_pos, r2_neg, multiplier;

    double energy ();
    void   dist (const SinCos& B);
    void   init_deriv ();
    double daz (const SinCos& B) const;
    double del (const SinCos& B) const;
    double rdel (const SinCos& B) const;

  public:
    SinCos (const gsl_vector* v, size_t index);
    double f (const SinCos& B);
    void   df (const SinCos& B, gsl_vector* deriv, size_t i, size_t j);
    double fdf (const SinCos& B, gsl_vector* deriv, size_t i, size_t j);
};

double energy_f (const gsl_vector* x, void* params);
void   energy_df (const gsl_vector* x, void* params, gsl_vector* df);
void   energy_fdf (const gsl_vector* x, void* params, double* f, gsl_vector* df);

void range (double& azimuth, double& elevation);

void run () {
  size_t niter = 10000;
  float target_power = 2.0;

  Options opt = get_options ("power");
  if (opt.size())
    target_power = opt[0][0];

  opt = get_options ("niter");
  if (opt.size())
    niter = opt[0][0];

  ndirs = to<int> (argument[0]);

  if (get_options ("unipolar").size())
    bipolar = false;

  Math::RNG    rng;
  Math::Vector<double> v (2*ndirs);

  for (size_t n = 0; n < 2*ndirs; n+=2) {
    v[n] =  Math::pi * (2.0 * rng.uniform() - 1.0);
    v[n+1] = std::asin (2.0 * rng.uniform() - 1.0);
  }

  gsl_multimin_function_fdf fdf;

  fdf.f = energy_f;
  fdf.df = energy_df;
  fdf.fdf = energy_fdf;
  fdf.n = 2*ndirs;

  gsl_multimin_fdfminimizer* minimizer =
    gsl_multimin_fdfminimizer_alloc (gsl_multimin_fdfminimizer_conjugate_fr, 2*ndirs);

  {
    ProgressBar progress ("Optimising directions...");
    for (power = -1.0; power >= -target_power/2.0; power *= 2.0) {
      INFO ("setting power = " + str (-power*2.0));
      gsl_multimin_fdfminimizer_set (minimizer, &fdf, v.gsl(), 0.01, 1e-4);

      for (size_t iter = 0; iter < niter; iter++) {

        int status = gsl_multimin_fdfminimizer_iterate (minimizer);

        //for (size_t n = 0; n < 2*ndirs; ++n)
          //std::cout << gsl_vector_get (minimizer->x, n) << " " << gsl_vector_get (minimizer->gradient, n) << "\n";

        if (iter%10 == 0)
          INFO ("[ " + str (iter) + " ] (pow = " + str (-power*2.0) + ") E = " + str (minimizer->f)
          + ", grad = " + str (gsl_blas_dnrm2 (minimizer->gradient)));

        if (status) {
          INFO (std::string ("iteration stopped: ") + gsl_strerror (status));
          break;
        }

        progress.set_text ("Optimising directions (power " + str(-2.0*power) + ", current energy: " + str(minimizer->f, 8) + ")...");
        ++progress;
      }
      gsl_vector_memcpy (v.gsl(), minimizer->x);
    }
  }

  Math::Matrix<double> directions (ndirs, 2);
  for (size_t n = 0; n < ndirs; n++) {
    double az = gsl_vector_get (minimizer->x, 2*n);
    double el = gsl_vector_get (minimizer->x, 2*n+1);
    range (az, el);
    directions (n, 0) = az;
    directions (n, 1) = el;
  }

  gsl_multimin_fdfminimizer_free (minimizer);

  DWI::Directions::save (directions, argument[1], get_options ("cartesian").size());
}

inline double SinCos::energy ()
{
  double E = pow (r2_neg, power);
  if (bipolar) E += pow (r2_pos, power);
  return E;
}

inline void SinCos::dist (const SinCos& B)
{
  double a1 = cos_az*sin_el;
  double b1 = B.cos_az*B.sin_el;
  double a2 = sin_az*sin_el;
  double b2 = B.sin_az*B.sin_el;
  r2_neg = Math::pow2(a1-b1) + Math::pow2(a2-b2) + Math::pow2(cos_el-B.cos_el);
  r2_pos = bipolar ? Math::pow2(a1+b1) + Math::pow2(a2+b2) + Math::pow2(cos_el+B.cos_el) : 0.0;
}

inline void SinCos::init_deriv ()
{
  multiplier = pow (r2_neg, power-1.0);
  if (bipolar) multiplier -= pow (r2_pos, power-1.0);
  multiplier *= 2.0 * power;
}

inline double SinCos::daz (const SinCos& B) const
{
  return multiplier * (cos_az*sin_el*B.sin_az*B.sin_el - sin_az*sin_el*B.cos_az*B.sin_el);
}

inline double SinCos::del (const SinCos& B) const
{
  return multiplier * (cos_az*cos_el*B.cos_az*B.sin_el + sin_az*cos_el*B.sin_az*B.sin_el - sin_el*B.cos_el);
}

inline double SinCos::rdel (const SinCos& B) const
{
  return multiplier * (B.cos_az*B.cos_el*cos_az*sin_el + B.sin_az*B.cos_el*sin_az*sin_el - B.sin_el*cos_el);
}

inline SinCos::SinCos (const gsl_vector* v, size_t index)
{
  //double az = index > 1 ? gsl_vector_get (v, 2*index-3) : 0.0;
  //double el = index ? gsl_vector_get (v, 2*index-2) : 0.0;
  double az = gsl_vector_get (v, 2*index);
  double el = gsl_vector_get (v, 2*index+1);
  cos_az = std::cos (az);
  sin_az = std::sin (az);
  cos_el = std::cos (el);
  sin_el = std::sin (el);
}

inline double SinCos::f (const SinCos& B)
{
  dist (B);
  return energy();
}

inline void SinCos::df (const SinCos& B, gsl_vector* deriv, size_t i, size_t j)
{
  dist (B);
  init_deriv ();
  double d = daz (B);
  *gsl_vector_ptr (deriv, 2*i) -= d;
  *gsl_vector_ptr (deriv, 2*i+1) -= del (B);
  *gsl_vector_ptr (deriv, 2*j) += d;
  *gsl_vector_ptr (deriv, 2*j+1) -= rdel (B);
}

inline double SinCos::fdf (const SinCos& B, gsl_vector* deriv, size_t i, size_t j)
{
  df (B, deriv, i, j);
  return energy();
}

double energy_f (const gsl_vector* x, void* params)
{
  double  E = 0.0;
  for (size_t i = 0; i < ndirs; i++) {
    SinCos I (x, i);
    for (size_t j = i+1; j < ndirs; j++)
      E += 2.0 * I.f (SinCos (x, j));
  }
  return E;
}

void energy_df (const gsl_vector* x, void* params, gsl_vector* df)
{
  gsl_vector_set_zero (df);
  for (size_t i = 0; i < ndirs; i++) {
    SinCos I (x, i);
    for (size_t j = i+1; j < ndirs; j++)
      I.df (SinCos (x, j), df, i, j);
  }
}

void energy_fdf (const gsl_vector* x, void* params, double* f, gsl_vector* df)
{
  *f = 0.0;
  gsl_vector_set_zero (df);
  for (size_t i = 0; i < ndirs; i++) {
    SinCos I (x, i);
    for (size_t j = i+1; j < ndirs; j++)
      *f += 2.0 * I.fdf (SinCos (x, j), df, i, j);
  }
}

inline void range (double& azimuth, double& elevation)
{
  while (elevation < 0.0) elevation += 2.0*Math::pi;
  while (elevation >= 2.0*Math::pi) elevation -= 2.0*Math::pi;
  if (elevation >= Math::pi) {
    elevation = 2.0*Math::pi - elevation;
    azimuth -= Math::pi;
  }
  while (azimuth < -Math::pi) azimuth += 2.0*Math::pi;
  while (azimuth >= Math::pi) azimuth -= 2.0*Math::pi;
}

<commit_msg>Port dirgen over to new ProgressBar::update() method<commit_after>/*
    Copyright 2008 Brain Research Institute, Melbourne, Australia

    Written by J-Donald Tournier, 27/06/08.

    This file is part of MRtrix.

    MRtrix is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MRtrix is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <gsl/gsl_blas.h>
#include <gsl/gsl_multimin.h>

#include "command.h"
#include "progressbar.h"
#include "math/vector.h"
#include "math/matrix.h"
#include "math/rng.h"
#include "dwi/directions/file.h"

using namespace MR;
using namespace App;

void usage () {

DESCRIPTION
  + "generate a set of uniformly distributed directions using a bipolar electrostatic repulsion model.";

REFERENCES
  + "* Jones, D.; Horsfield, M. & Simmons, A. "
  "Optimal strategies for measuring diffusion in anisotropic systems by magnetic resonance imaging. "
  "Magnetic Resonance in Medicine, 42: 515-525 (1999)."

  + "* Papadakis, N. G.; Murrills, C. D.; Hall, L. D.; Huang, C. L.-H. & Adrian Carpenter, T. "
  "Minimal gradient encoding for robust estimation of diffusion anisotropy. "
  "Magnetic Resonance Imaging, 18: 671-679 (2000).";

ARGUMENTS
  + Argument ("ndir", "the number of directions to generate.").type_integer (6, 60, std::numeric_limits<int>::max())
  + Argument ("dirs", "the text file to write the directions to, as [ az el ] pairs.").type_file_out();

OPTIONS
  + Option ("power", "specify exponent to use for repulsion power law (default: 2).")
  + Argument ("exp").type_integer (2, 2, std::numeric_limits<int>::max())

  + Option ("niter", "specify the maximum number of iterations to perform (default: 10000).")
  + Argument ("num").type_integer (1, 10000, std::numeric_limits<int>::max())

  + Option ("unipolar", "optimise assuming a unipolar electrostatic repulsion model rather than the bipolar model normally assumed in DWI")

  + Option ("cartesian", "Output the directions in Cartesian coordinates [x y z] instead of [az el].");

}

namespace
{
  double power = -1.0;
  size_t   ndirs = 0;
  bool bipolar = true;
}

class SinCos
{
  protected:
    double cos_az, sin_az, cos_el, sin_el;
    double r2_pos, r2_neg, multiplier;

    double energy ();
    void   dist (const SinCos& B);
    void   init_deriv ();
    double daz (const SinCos& B) const;
    double del (const SinCos& B) const;
    double rdel (const SinCos& B) const;

  public:
    SinCos (const gsl_vector* v, size_t index);
    double f (const SinCos& B);
    void   df (const SinCos& B, gsl_vector* deriv, size_t i, size_t j);
    double fdf (const SinCos& B, gsl_vector* deriv, size_t i, size_t j);
};

double energy_f (const gsl_vector* x, void* params);
void   energy_df (const gsl_vector* x, void* params, gsl_vector* df);
void   energy_fdf (const gsl_vector* x, void* params, double* f, gsl_vector* df);

void range (double& azimuth, double& elevation);

void run () {
  size_t niter = 10000;
  float target_power = 2.0;

  Options opt = get_options ("power");
  if (opt.size())
    target_power = opt[0][0];

  opt = get_options ("niter");
  if (opt.size())
    niter = opt[0][0];

  ndirs = to<int> (argument[0]);

  if (get_options ("unipolar").size())
    bipolar = false;

  Math::RNG    rng;
  Math::Vector<double> v (2*ndirs);

  for (size_t n = 0; n < 2*ndirs; n+=2) {
    v[n] =  Math::pi * (2.0 * rng.uniform() - 1.0);
    v[n+1] = std::asin (2.0 * rng.uniform() - 1.0);
  }

  gsl_multimin_function_fdf fdf;

  fdf.f = energy_f;
  fdf.df = energy_df;
  fdf.fdf = energy_fdf;
  fdf.n = 2*ndirs;

  gsl_multimin_fdfminimizer* minimizer =
    gsl_multimin_fdfminimizer_alloc (gsl_multimin_fdfminimizer_conjugate_fr, 2*ndirs);

  {
    ProgressBar progress ("Optimising directions...");
    for (power = -1.0; power >= -target_power/2.0; power *= 2.0) {
      INFO ("setting power = " + str (-power*2.0));
      gsl_multimin_fdfminimizer_set (minimizer, &fdf, v.gsl(), 0.01, 1e-4);

      for (size_t iter = 0; iter < niter; iter++) {

        int status = gsl_multimin_fdfminimizer_iterate (minimizer);

        //for (size_t n = 0; n < 2*ndirs; ++n)
          //std::cout << gsl_vector_get (minimizer->x, n) << " " << gsl_vector_get (minimizer->gradient, n) << "\n";

        if (iter%10 == 0)
          INFO ("[ " + str (iter) + " ] (pow = " + str (-power*2.0) + ") E = " + str (minimizer->f)
          + ", grad = " + str (gsl_blas_dnrm2 (minimizer->gradient)));

        if (status) {
          INFO (std::string ("iteration stopped: ") + gsl_strerror (status));
          break;
        }

        progress.update ([&]() { return "Optimising directions (power " + str(-2.0*power) + ", current energy: " + str(minimizer->f, 8) + ")..."; });
      }
      gsl_vector_memcpy (v.gsl(), minimizer->x);
    }
  }

  Math::Matrix<double> directions (ndirs, 2);
  for (size_t n = 0; n < ndirs; n++) {
    double az = gsl_vector_get (minimizer->x, 2*n);
    double el = gsl_vector_get (minimizer->x, 2*n+1);
    range (az, el);
    directions (n, 0) = az;
    directions (n, 1) = el;
  }

  gsl_multimin_fdfminimizer_free (minimizer);

  DWI::Directions::save (directions, argument[1], get_options ("cartesian").size());
}

inline double SinCos::energy ()
{
  double E = pow (r2_neg, power);
  if (bipolar) E += pow (r2_pos, power);
  return E;
}

inline void SinCos::dist (const SinCos& B)
{
  double a1 = cos_az*sin_el;
  double b1 = B.cos_az*B.sin_el;
  double a2 = sin_az*sin_el;
  double b2 = B.sin_az*B.sin_el;
  r2_neg = Math::pow2(a1-b1) + Math::pow2(a2-b2) + Math::pow2(cos_el-B.cos_el);
  r2_pos = bipolar ? Math::pow2(a1+b1) + Math::pow2(a2+b2) + Math::pow2(cos_el+B.cos_el) : 0.0;
}

inline void SinCos::init_deriv ()
{
  multiplier = pow (r2_neg, power-1.0);
  if (bipolar) multiplier -= pow (r2_pos, power-1.0);
  multiplier *= 2.0 * power;
}

inline double SinCos::daz (const SinCos& B) const
{
  return multiplier * (cos_az*sin_el*B.sin_az*B.sin_el - sin_az*sin_el*B.cos_az*B.sin_el);
}

inline double SinCos::del (const SinCos& B) const
{
  return multiplier * (cos_az*cos_el*B.cos_az*B.sin_el + sin_az*cos_el*B.sin_az*B.sin_el - sin_el*B.cos_el);
}

inline double SinCos::rdel (const SinCos& B) const
{
  return multiplier * (B.cos_az*B.cos_el*cos_az*sin_el + B.sin_az*B.cos_el*sin_az*sin_el - B.sin_el*cos_el);
}

inline SinCos::SinCos (const gsl_vector* v, size_t index)
{
  //double az = index > 1 ? gsl_vector_get (v, 2*index-3) : 0.0;
  //double el = index ? gsl_vector_get (v, 2*index-2) : 0.0;
  double az = gsl_vector_get (v, 2*index);
  double el = gsl_vector_get (v, 2*index+1);
  cos_az = std::cos (az);
  sin_az = std::sin (az);
  cos_el = std::cos (el);
  sin_el = std::sin (el);
}

inline double SinCos::f (const SinCos& B)
{
  dist (B);
  return energy();
}

inline void SinCos::df (const SinCos& B, gsl_vector* deriv, size_t i, size_t j)
{
  dist (B);
  init_deriv ();
  double d = daz (B);
  *gsl_vector_ptr (deriv, 2*i) -= d;
  *gsl_vector_ptr (deriv, 2*i+1) -= del (B);
  *gsl_vector_ptr (deriv, 2*j) += d;
  *gsl_vector_ptr (deriv, 2*j+1) -= rdel (B);
}

inline double SinCos::fdf (const SinCos& B, gsl_vector* deriv, size_t i, size_t j)
{
  df (B, deriv, i, j);
  return energy();
}

double energy_f (const gsl_vector* x, void* params)
{
  double  E = 0.0;
  for (size_t i = 0; i < ndirs; i++) {
    SinCos I (x, i);
    for (size_t j = i+1; j < ndirs; j++)
      E += 2.0 * I.f (SinCos (x, j));
  }
  return E;
}

void energy_df (const gsl_vector* x, void* params, gsl_vector* df)
{
  gsl_vector_set_zero (df);
  for (size_t i = 0; i < ndirs; i++) {
    SinCos I (x, i);
    for (size_t j = i+1; j < ndirs; j++)
      I.df (SinCos (x, j), df, i, j);
  }
}

void energy_fdf (const gsl_vector* x, void* params, double* f, gsl_vector* df)
{
  *f = 0.0;
  gsl_vector_set_zero (df);
  for (size_t i = 0; i < ndirs; i++) {
    SinCos I (x, i);
    for (size_t j = i+1; j < ndirs; j++)
      *f += 2.0 * I.fdf (SinCos (x, j), df, i, j);
  }
}

inline void range (double& azimuth, double& elevation)
{
  while (elevation < 0.0) elevation += 2.0*Math::pi;
  while (elevation >= 2.0*Math::pi) elevation -= 2.0*Math::pi;
  if (elevation >= Math::pi) {
    elevation = 2.0*Math::pi - elevation;
    azimuth -= Math::pi;
  }
  while (azimuth < -Math::pi) azimuth += 2.0*Math::pi;
  while (azimuth >= Math::pi) azimuth -= 2.0*Math::pi;
}

<|endoftext|>


<commit_before>// Take a dir full of output images grabbed by
// hand using imageclipper
// Decode the bounding rect from the fileame
// Go back to the original video and generate
// shifted versions of the rects for training
// calibration nets
#include <sys/types.h>
#include <dirent.h>

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

#include <opencv2/opencv.hpp>

#include "imageShift.hpp"
#include "imageclipper_read.hpp"

using namespace std;
using namespace cv;

string srcPath = "/home/kjaget/ball_videos/test/";
string outPath = "shifts";
int main(void)
{
	const double targetAR = 1.0;
	DIR *dirp = opendir(".");
	struct dirent *dp;
	vector<string> image_names;
	if (!dirp)
		return -1;

	while ((dp = readdir(dirp)) != NULL)
	{
		if (strstr(dp->d_name, ".png") )
			image_names.push_back(dp->d_name);
	}
	closedir(dirp);
	cout << "Read " << image_names.size() << " image names" << endl;

	createShiftDirs(outPath);
	RNG rng(time(NULL));
	Mat mat;
	Rect rect;
	string inFileName;
	int frame;
	for (vector<string>::iterator it = image_names.begin(); it != image_names.end(); ++it)
	{
		if (getFrameAndRect(*it, srcPath, targetAR, inFileName, frame, mat, rect))
		{

			stringstream write_name;
			write_name << inFileName;
			write_name << "_" << setw(5) << setfill('0') << frame;
			write_name << "_" << setw(4) << rect.x;
			write_name << "_" << setw(4) << rect.y;
			write_name << "_" << setw(4) << rect.width;
			write_name << "_" << setw(4) << rect.height;
			write_name << ".png";

			doShifts(mat, rect, rng, Point3f(0,0,2.0*M_PI), 10, outPath, write_name.str());
		}
	}
	return 0;
}

<commit_msg>Fewer copies of shifted images, more in line with grab_chroma<commit_after>// Take a dir full of output images grabbed by
// hand using imageclipper
// Decode the bounding rect from the fileame
// Go back to the original video and generate
// shifted versions of the rects for training
// calibration nets
#include <sys/types.h>
#include <dirent.h>

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

#include <opencv2/opencv.hpp>

#include "imageShift.hpp"
#include "imageclipper_read.hpp"

using namespace std;
using namespace cv;

string srcPath = "/home/kjaget/ball_videos/white_floor/";
string outPath = "shifts";
int main(void)
{
	const double targetAR = 1.0;
	DIR *dirp = opendir(".");
	struct dirent *dp;
	vector<string> image_names;
	if (!dirp)
		return -1;

	while ((dp = readdir(dirp)) != NULL)
	{
		if (strstr(dp->d_name, ".png") )
			image_names.push_back(dp->d_name);
	}
	closedir(dirp);
	cout << "Read " << image_names.size() << " image names" << endl;

	createShiftDirs(outPath);
	RNG rng(time(NULL));
	Mat mat;
	Rect rect;
	string inFileName;
	int frame;
	for (vector<string>::iterator it = image_names.begin(); it != image_names.end(); ++it)
	{
		if (getFrameAndRect(*it, srcPath, targetAR, inFileName, frame, mat, rect))
		{

			stringstream write_name;
			write_name << inFileName;
			write_name << "_" << setw(5) << setfill('0') << frame;
			write_name << "_" << setw(4) << rect.x;
			write_name << "_" << setw(4) << rect.y;
			write_name << "_" << setw(4) << rect.width;
			write_name << "_" << setw(4) << rect.height;
			write_name << ".png";

			doShifts(mat, rect, rng, Point3f(0,0,2.0*M_PI), 4, outPath, write_name.str());
		}
	}
	return 0;
}

<|endoftext|>