Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formula chain exceeded the 1000 limit #7

Closed
defrule opened this issue Mar 12, 2019 · 11 comments
Closed

Formula chain exceeded the 1000 limit #7

defrule opened this issue Mar 12, 2019 · 11 comments

Comments

@defrule
Copy link

defrule commented Mar 12, 2019

I tried using modelx to similar a unit account deducting charges, applying growth. I wanted to project up to 720 months but there seems to be a limit that causes and error. The code I'm running is below:

from modelx import *

model, space = new_model(), new_space()


@defcells
def unit_reserve_opening(t):
    if t == 1:
        return 100000
    else:
        return unit_reserve_closing(t-1)


@defcells
def unit_reserve_after_growth(t):
    return unit_reserve_opening(t) * (1 + 0.05) ** (1 / 12.0)


@defcells
def internal_amc(t):
    return unit_reserve_after_growth(t) * 0.005 / 12


@defcells
def unit_reserve_after_charges(t):
    return unit_reserve_after_growth(t) - internal_amc(t)


@defcells
def unit_reserve_closing(t):
    return unit_reserve_after_charges(t) - 100


x = unit_reserve_after_charges[300]
print(unit_reserve_after_charges.series)
@fumitoh
Copy link
Owner

fumitoh commented Mar 13, 2019

For now, to circumvent the error, you can calculate unit_reserve_after_charges at shorter steps first before calculating unit_reserve_after_charges[300] to avoid long recursive reference. I plan to extend modelx to allow infinite length of recursion in future release.

@fumitoh
Copy link
Owner

fumitoh commented Mar 30, 2019

set_recursion API function is introduced in modelx v0.0.21.

http://docs.modelx.io/en/latest/reference/generated/modelx.set_recursion.html#modelx.set_recursion

You can increase the max recursion from 1000 but Python may crash due to callstack being too deep.

@jarel1024
Copy link

I use to project the a whole life policy cashflow by month,the callstack Could be more than 1000. So I want to ask if there is any good ways to avoid python crash? Or you will solve this problem in the future?

@fumitoh
Copy link
Owner

fumitoh commented Apr 10, 2019

Please see #7 (comment). Is this answer not sufficient?

@jarel1024
Copy link

I did not explain my problem clearly. Your answer is clearly. I means that my python crash due to the deep callstack(recursion about 2000 or more).Now I use thread to run the model. By setting “threading.stack_size”, It works.

@fumitoh
Copy link
Owner

fumitoh commented Apr 11, 2019

Thanks for reporting another workaround.
Have you tried resource.setrlimit?
This is suggested here: https://stackoverflow.com/questions/5061582/setting-stacksize-in-a-python-script
If this works, then you don't need to bother creating a thread. Let me know how it works.

@jarel1024
Copy link

Since I run the model in windows platform, and I find there is no resource module in windows version’s python. Maybe there is some other module which can set the stack size. But I’m not sure. By the way, your module is really great for Actuary’s work.

@fumitoh
Copy link
Owner

fumitoh commented Apr 12, 2019

You're right. It's not available on Windows platform. There doesn't seem any way to change the stack size on Windows platform other than creating a new thread as you suggested. I think I'm going to reflect your suggestion. Can you post a very simple script to show how you use threading.stack_size with modelx? Thanks for the cheering, I appreciate it.

@defrule
Copy link
Author

defrule commented Apr 12, 2019

sys.setrecursionlimit(30000) seemed to work for me. I'm on a Mac.

@fumitoh
Copy link
Owner

fumitoh commented Apr 14, 2019

sys.setrecursionlimit doesn't increase stack size at least on Windows.
Below is the test script I managed to run. The max size threading.stack_size accepts is 0xFFFFFFF in hexadecimal, or 268,435,455 bytes.
The max depth of formula recursion was somewhere between 85000 and 90000 on Windows 64bit.
Counter-intuitively, 32bit version of Python on Windows can go twice as deep as 64bit ver.

import threading
import sys
import modelx as mx

N = 85000 # or 170000 for 32-bit win

sys.setrecursionlimit(10**6)
mx.set_recursion(N)

m, s = mx.new_model(), mx.new_space()

@mx.defcells
def foo(x):
    if x == 0:
        return 0
    else:
        return foo(x-1) + 1

threading.stack_size(0xFFFFFFF) 

def runfoo():
    global result
    result = foo(N)

th = threading.Thread(target=runfoo)

th.start()
th.join()

print(result)

@fumitoh
Copy link
Owner

fumitoh commented Apr 18, 2019

6a0fcd1 Implements cells formula execution in a single thread with the max stack size.
I'll keep this issue open for a while to see if anybody has problems with this solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants