<commit_before>#!/usr/bin/python
'''
Contains general code related to all optimization techniques.

Instead of keeping parameters in a list, we could store them based
upon their MM3* index (row, column). Then we wouldn't need to save
entire parameter sets, significantly reducing the memory usage.
'''
import argparse
import copy
import logging
import os

from calculate import run_calculate
from compare import calc_x2, import_steps
from datatypes import FF, MM3, UnallowedNegative

logger = logging.getLogger(__name__)

class Optimizer(object):
    def __init__(self):
        self.com_ref = None
        self.com_cal = None
        self.data_ref = None
        self.init_ff = None

    def central_diff_derivs(self, init_ff, central_ffs):
        for i in xrange(0, len(central_ffs), 2):
            init_ff.params[i / 2].der1 = (central_ffs[i].x2 - central_ffs[i + 1].x2) * 0.5 # 18
            init_ff.params[i / 2].der2 = central_ffs[i].x2 + central_ffs[i + 1].x2 - 2 * init_ff.x2 # 19
        logger.info('1st derivatives: {}'.format([x.der1 for x in init_ff.params]))
        logger.info('2nd derivatives: {}'.format([x.der2 for x in init_ff.params]))

    def calc_x2_ff(self, ff, save_data=False):
        self.init_ff.export_ff(params=ff.params)
        if save_data:
            ff.data = run_calculate(self.com_cal.split())
            ff.x2 = calc_x2(ff.data, self.data_ref)
        else:
            ff.x2 = calc_x2(self.com_cal, self.data_ref)
        logger.info('{}: {}'.format(ff.method, ff.x2))

    def params_diff(self, params, mode='central'):
        '''
        Perform forward or central differentiation of parameters.

        Need means of adjusting the parameter step size. When checking the parameter,
        perhaps it should account for the adjusted step size.

        I would say this function is rather memory insensitive and could
        use some improvements.
        '''
        logger.info('{} differentiation - {} parameters'.format(mode, len(params)))
        import_steps(params)
        diff_ffs = []
        for i, param in enumerate(params):
            while True:
                try:
                    ff_forward = FF()
                    ff_forward.params = copy.deepcopy(params)
                    ff_forward.method = 'forward {} {}'.format(param.mm3_row, param.mm3_col)
                    # commented region now done in compare.import_steps
                    # if isinstance(ff_forward.params[i].step, basestring):
                    #     ff_forward.params[i].value += ff_forward.params[i].value * \
                    #         float(ff_forward.params[i].step)
                    # else:
                    #     ff_forward.params[i].value += ff_forward.params[i].step
                    ff_forward.params[i].value += ff_forward.params[i].step
                    ff_forward.params[i].check_value()
                    if mode == 'central':
                        ff_backward = FF()
                        ff_backward.method = 'backward {} {}'.format(param.mm3_row, param.mm3_col)
                        ff_backward.params = copy.deepcopy(params)
                        ff_backward.params[i].value -= ff_backward.params[i].step
                        ff_backward.params[i].check_value()
                    break
                except UnallowedNegative as e:
                    logger.warning(e.message)
                    logger.warning('changing step size of {} from {} to {}'.format(
                            param, param.step, param.value * 0.05))
                    param.step = param.value * 0.05
                finally:
                    ff_forward.display_params()
                    diff_ffs.append(ff_forward)
                    if mode == 'central':
                        ff_backward.display_params()
                        diff_ffs.append(ff_backward)
        logger.info('generated {} force fields for {} differentiation'.format(len(diff_ffs), mode))
        return diff_ffs
<commit_msg>Fixed IndexError that originated from differentiation of parameters.<commit_after>#!/usr/bin/python
'''
Contains general code related to all optimization techniques.

Instead of keeping parameters in a list, we could store them based
upon their MM3* index (row, column). Then we wouldn't need to save
entire parameter sets, significantly reducing the memory usage.
'''
import argparse
import copy
import logging
import os

from calculate import run_calculate
from compare import calc_x2, import_steps
from datatypes import FF, MM3, UnallowedNegative

logger = logging.getLogger(__name__)

class Optimizer(object):
    def __init__(self):
        self.com_ref = None
        self.com_cal = None
        self.data_ref = None
        self.init_ff = None

    def central_diff_derivs(self, init_ff, central_ffs):
        for i in xrange(0, len(central_ffs), 2):
            init_ff.params[i / 2].der1 = (central_ffs[i].x2 - central_ffs[i + 1].x2) * 0.5 # 18
            init_ff.params[i / 2].der2 = central_ffs[i].x2 + central_ffs[i + 1].x2 - 2 * init_ff.x2 # 19
        logger.info('1st derivatives: {}'.format([x.der1 for x in init_ff.params]))
        logger.info('2nd derivatives: {}'.format([x.der2 for x in init_ff.params]))

    def calc_x2_ff(self, ff, save_data=False):
        self.init_ff.export_ff(params=ff.params)
        if save_data:
            ff.data = run_calculate(self.com_cal.split())
            ff.x2 = calc_x2(ff.data, self.data_ref)
        else:
            ff.x2 = calc_x2(self.com_cal, self.data_ref)
        logger.info('{}: {}'.format(ff.method, ff.x2))

    def params_diff(self, params, mode='central'):
        '''
        Perform forward or central differentiation of parameters.

        Need means of adjusting the parameter step size. When checking the parameter,
        perhaps it should account for the adjusted step size.

        I would say this function is rather memory insensitive and could
        use some improvements.
        '''
        logger.info('{} differentiation - {} parameters'.format(mode, len(params)))
        import_steps(params)
        diff_ffs = []
        for i, param in enumerate(params):
            while True:
                try:
                    ff_forward = FF()
                    ff_forward.params = copy.deepcopy(params)
                    ff_forward.method = 'forward {} {}'.format(param.mm3_row, param.mm3_col)
                    # commented region now done in compare.import_steps
                    # if isinstance(ff_forward.params[i].step, basestring):
                    #     ff_forward.params[i].value += ff_forward.params[i].value * \
                    #         float(ff_forward.params[i].step)
                    # else:
                    #     ff_forward.params[i].value += ff_forward.params[i].step
                    ff_forward.params[i].value += ff_forward.params[i].step
                    ff_forward.params[i].check_value()
                    if mode == 'central':
                        ff_backward = FF()
                        ff_backward.method = 'backward {} {}'.format(param.mm3_row, param.mm3_col)
                        ff_backward.params = copy.deepcopy(params)
                        ff_backward.params[i].value -= ff_backward.params[i].step
                        ff_backward.params[i].check_value()
                except UnallowedNegative as e:
                    logger.warning(e.message)
                    logger.warning('changing step size of {} from {} to {}'.format(
                            param, param.step, param.value * 0.05))
                    param.step = param.value * 0.05
                else:
                    ff_forward.display_params()
                    diff_ffs.append(ff_forward)
                    if mode == 'central':
                        ff_backward.display_params()
                        diff_ffs.append(ff_backward)
                    break
        logger.info('generated {} force fields for {} differentiation'.format(len(diff_ffs), mode))
        return diff_ffs

{'fraction_non_alphanumeric': 0.10229254921505108, 'fraction_numerical': 0.01071517567904311, 'mean_word_length': 1.9199708985085486, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2790923', 'n_tokens_mistral': 2395, 'n_tokens_neox': 2201, 'n_words': 551}