Initializing help system before first use

Mandelbrot


Type: Programming
Rating: 5 (difficult)
Description: This model implements a queued execution of remote models (modelmandelhttpsub.mos) with result graphics displayed in a web browser controlled by the master (root) model mandelhttp.mos.
On each node in the specified list we start K model instances. Each submodel instance is sent a rectangular area for which to calculate the pixel color values based on the Mandelbrot function f(z) = z^2 + c where z,c are complex numbers.
The results are passed back via a file (located at the same place as this master model, no write access to remote instances is required). Once the result has been displayed, the submodel is restarted for a new data set.
File(s): mandelhttp.mos, mandelhttpsub.mos
Data file(s): mandelhttp.html, jquery-2.0.0.min.js

mandelhttp.mos
(!*******************************************************
   Mosel Example Problems
   ======================

   file mandelhttp.mos
   ```````````````````
   Mandelbrot function: f(z) = z^2 + c with z,c complex numbers.

   Master model communicating with HTML GUI and coordinating
   all submodels.
   On each node in the list NODESLIST we start K model instances.
   Each submodel instance is sent a rectangular area for which
   to calculate the pixel color values. The results are passed
   back via a file (located at the same place as this master model,
   no write access to remote instances is required).
   Once the result has been displayed, the submodel is
   restarted for a new data set.

   - Testing HTTP -
   
   (c) 2013 Fair Isaac Corporation
       author: Y. Colombani, S. Heipcke, May 2013
  *******************************************************!)

model mandelbrothttp
  uses 'mmhttp','mmsystem';

  parameters
    CONFIG=0                    ! Color scheme and zoom
                                ! >>>>> Try values 0,1,2,3,4
    K = 2                       ! Number of submodels per Mosel instance
    NUMPX = 1000                ! Graphic size in pixels
    NUM = 0                     ! Model ID
    CWIDTH =1000                ! Window height (>=NUMPX)
    CHEIGHT =1000               ! Window width (>=NUMPX)
    SW =100                     ! Size of subproblems in pixels
  end-parameters

!!! Configure this list with machines in your local network, 
!!! there must be at least 1 entry in this list.
  NODELIST:=["",""] 
  MAXND:= 8                     ! Maximum node number expected by HTML display
  while (NODELIST.size*K>MAXND) do
    writeln("Removing node ", gettail(NODELIST,1))
    cuttail(NODELIST,1)
  end-do
  if NODELIST.size=0 then
    writeln("Empty node list."); exit(1)
  end-if  

  declarations
    M: integer                  ! Number of remote Mosel instances
    A: range
    B: range
    NODES: array(B) of string
  end-declarations
 
  forall(n in NODELIST, M as counter) NODES(M):=n
  A:= 1..M*K
  finalise(A)
  finalise(B)

  declarations
    modPar: array(A) of Model
    moselInst: array(B) of Mosel
    modid: array(set of integer) of integer  ! Model index for model IDs
    modstartct, modendct, config: integer
    nbrunning:integer
    running:boolean
    active:array(A) of boolean
    nodnam:array(A) of string
    ev: Event

    XMin,XMax,YMin,YMax,HX,HY:real
    OffsetX,OffsetY:integer
    MAX_ITER: integer
    stoppressed: integer
    SQUARE: array(Squares:range,1..4) of integer
    RS=0..(SW*SW*3)
    solrec=record
            x,y:integer
            h,w:integer
	    points:array(RS) of integer
	   end-record
    solutions:list of solrec
    waitimg:list of integer
    finished:boolean
  end-declarations 
 
!***************** Subroutines ******************

!**********************
!* Setup configuration
!**********************
  procedure set_mandelbrot_config(c: integer)
    if c = 0 then
      XMin:=-1.5; XMax:=0.5
      YMin:=-1; YMax:=1
    elif c = 1 then
      XMin:=-0.90; XMax:=-0.915
      YMin:=-0.245; YMax:=-0.23 
    elif c = 2 then
      XMin:=-0.9; XMax:=-0.98
      YMin:=-0.3; YMax:=-0.22
    elif c = 3 then
      XMin:=-0.91; XMax:=-0.94
      YMin:=-0.3; YMax:=-0.27
    elif c = 4 then
      XMin:=-0.926; XMax:=-0.934
      YMin:=-0.264; YMax:=-0.256
    end-if 

    HX:=(XMax-XMin)/NUMPX
    HY:=(YMax-YMin)/NUMPX
    OffsetX:=-round(XMin/HX)
    OffsetY:=-round(YMin/HY)

    forall(s,t in 1..ceil(NUMPX/SW), sqct as counter) do
      SQUARE(sqct,1):= round(XMin/HX)+(s-1)*SW 
      SQUARE(sqct,2):= minlist(round(XMin/HX)+s*SW-1,round(XMax/HX)) 
      SQUARE(sqct,3):= round(YMin/HY)+(t-1)*SW 
      SQUARE(sqct,4):= minlist(round(YMin/HY)+t*SW-1,round(YMax/HY))
    end-do
  end-procedure

!***************
!* Start solve
!***************
  procedure cmdstart(r:integer)
   initialisations from httpreqfile(r)
    config
   end-initialisations
   stoppressed:=-1
   set_mandelbrot_config(config)
   writeln("Starting with config ",config)
                                   ! Start first lot of remote model executions
   modstartct:=0
   nbrunning:=0
   modendct:=0
   forall(n in 1..minlist(M*K,getsize(Squares))) do
     modstartct+=1
     nbrunning+=1
     active(n):=true
     run(modPar(n), "MINX="+SQUARE(modstartct,1) + ",MAXX="+
                    SQUARE(modstartct,2) + ",MINY="+ SQUARE(modstartct,3) +
                    ",MAXY="+SQUARE(modstartct,4) + ",NUM="+modstartct +
                    ",HX="+HX + ",HY="+HY + ",NUMPX="+NUMPX +
                    ",CONFIG="+config)
   end-do
   running:=true
   httpreply(r)
  end-procedure

!***************************************************
!* Return an array indicating activity of each node
!***************************************************
  procedure updnodes(r:integer)
   declarations
    tosend:record
     act:array(A) of boolean
     name:array(A) of string
     end-record
   end-declarations
   tosend.act:=active
   tosend.name:=nodnam
   httpreplyjson(r,tosend)
  end-procedure

!*******************
!* Save a solution
!*******************
  procedure save_sol(num: integer)
    declarations
      sol:solrec
    end-declarations

    initializations from "bin:solmod"+num+".txt"
      sol
    end-initializations

    sol.x+=OffsetX
    sol.y+=OffsetY
    solutions+=[sol]
    fdelete("solmod"+num+".txt") 
  end-procedure

!**********************************
!* Process solution/request queues
!**********************************
  procedure updatequeues
   declarations
    sol:solrec
    req:integer
   end-declarations
   if solutions.size>0 and waitimg.size>0 then
    req:=getfirst(waitimg)
    cuthead(waitimg,1)
    sol:=getfirst(solutions)
    cuthead(solutions,1)
    httpreplyjson(req,sol)
   end-if
  end-procedure

!***************** Main ******************

! Start child nodes
  forall(i in B)
    if connect(moselInst(i), NODES(i))<>0 then exit(2); end-if

  if compile("g","mandelhttpsub.mos","tmp:ms.bim")<>0 then exit(3); end-if
  forall(j in A) do                ! Load models
    load(moselInst(j mod M + 1), modPar(j), "rmt:tmp:ms.bim")  
    modid(getid(modPar(j))):= j
  end-do

! Update node names
  forall(i in A)
    nodnam(i):=if(NODES(i mod M + 1)<>"", NODES(i mod M + 1), "(local)")

  stoppressed:=-1
  forall(i in A) active(i):=false

!  setparam("http_browser",'C:\Program Files (x86)\Internet explorer\iexplore.exe')
  setparam("http_startwb",true)
  setparam("http_listen","127.0.0.1")
  setparam("http_defport",2533)
  setparam("http_defpage","mandelhttp.html")
  httpstartsrv(".","mosel/")
  repeat
    wait
    ev:=getnextevent
    if ev.class=EVENT_HTTPNEW then
      req:=integer(ev.value)
      case httpreqlabel(req) of
        "end": do finished:=true; httpreply(req); end-do
        "updnodes": updnodes(req)
        "cmdstart": cmdstart(req)
        "cmdstop":
	   do
	    stoppressed:=req
	    writeln("Stopping")
	   end-do
        "updimg":
	   if running or getsize(solutions)>0 then
	    waitimg+=[req]
	   else
            httpreplyjson(req)
	   end-if
         else
    	  httpreply(req)
       end-case
    elif getclass(ev)=EVENT_END then
      modendct+=1 
      num:=modid(getfromid(ev))
      active(num):=false
      save_sol(num) 
      if modstartct<getsize(Squares) and (stoppressed<0) then
        modstartct+=1
        active(num):=true
        run(modPar(num), "MINX="+SQUARE(modstartct,1) + ",MAXX="+
                    SQUARE(modstartct,2) + ",MINY="+ SQUARE(modstartct,3) +
                    ",MAXY="+SQUARE(modstartct,4) + ",NUM="+num +
                    ",HX="+HX + ",HY="+HY + ",NUMPX="+NUMPX + 
                    ",CONFIG="+config)
      else
        nbrunning-=1
      end-if
      if (modendct>=getsize(Squares)) or (nbrunning<1) then
        updatequeues
        if stoppressed>=0 then
          httpreply(stoppressed)
          stoppressed:=-1
          while (waitimg.size>0) do
            req:=getfirst(waitimg)
            httpreplyjson(req)
            cuthead(waitimg,1)
          end-do
          solutions:=[]
        end-if
        modendct:=0
        running:=false
        writeln("Ready to start again")
      end-if
    end-if
    updatequeues
  until finished
  
end-model

mandelhttpsub.mos
(!*******************************************************
   Mosel Example Problems
   ======================

   file mandelhttpsub.mos
   ``````````````````````
   Mandelbrot function: f(z) = z^2 + c with z,c complex numbers.

   Submodel for solving the function for all points in the
   rectangular box (MINX,MINY,MAXX,MAXY).

   - Testing HTTP -
   
   (c) 2013 Fair Isaac Corporation
       author: Y. Colombani, S. Heipcke, May 2013
  *******************************************************!)

model "mandelbrot (sub)"
  uses "mmjobs" 
 
  parameters
    CONFIG=3                    ! Color scheme and zoom
    MINX = 0                    ! Min/Max X/Y coordinates of box solved by this model
    MAXX = 0
    MINY = 0
    MAXY = 0
    HX = 0.1                    ! Distance between points
    HY = 0.1
    NUM = 0                     ! Model ID
    MAX_ITER = 1000             ! Iteration limit for Mandelbrot function 
  end-parameters	

  declarations
    pixel=record
           r,g,b:integer
	  end-record
    RS=0..((MAXX-MINX+1)*(MAXY-MINY+1)*3)
    SOL:record
            x,y:integer
            h,w:integer
	    points:array(RS) of integer
	   end-record
    black,point:pixel
  end-declarations 
 

!***************** Subroutines ******************
  function PXcolor(r,g,b:real): pixel
    returned.r:=round(r)
    returned.g:=round(g)
    returned.b:=round(b)
  end-function 

! Color for a pixel on the screen    (x0,y0) = (x,y) co-ordinates of pixel
  function pixel_color(x0,y0: real): pixel
    x:= 0.0
    y:= 0.0
    iterct:= 0
 
    while ( x*x + y*y <= (2*2)  and  iterct < MAX_ITER ) do
      xtemp := x*x - y*y + x0
      y:= 2*x*y + y0
      x:= xtemp
      iterct += 1
    end-do
    if iterct = MAX_ITER then 
      returned := black
    else 
      if CONFIG = 0 then
       returned := PXcolor(round((iterct) mod 255), 255-round(iterct*2 mod 255), 255-round((ln(iterct)*40) mod 255))
      elif CONFIG = 1 then
       returned := PXcolor(round((iterct) mod 255), round((ln(iterct)*50) mod 255), 255-round(iterct mod 255))
      elif CONFIG = 2 then
       returned := PXcolor(iterct*3 mod 255, round(iterct*2 mod 255), 255-round(iterct*3 mod 255))
      elif CONFIG = 3 then
       returned := PXcolor(ln(iterct)*50 mod 255, round(iterct*2 mod 255), 255-round(iterct*1.5 mod 255))
      elif CONFIG = 4 then
       returned := PXcolor(255-(iterct mod 255), 255-round(iterct*2 mod 255), round(iterct mod 255))
      end-if
    end-if  
 end-function

!***************** Main ******************
  
 ! Do the actual calculation for a box and save the solution
   c:=0
   forall(y0 in MINY..MAXY,x0 in MINX..MAXX)
   do
    point:=pixel_color(x0*HX,y0*HY)
    SOL.points(c):=point.r
    SOL.points(c+1):=point.g
    SOL.points(c+2):=point.b
    c+=3
   end-do
   SOL.x:=MINX
   SOL.y:=MINY
   SOL.w:=MAXX-MINX+1
   SOL.h:=MAXY-MINY+1
   initializations to "bin:rmt:solmod"+NUM+".txt"
     SOL as "sol"
   end-initializations

   exit(NUM)

end-model 

© 2001-2019 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.