Initializing help system before first use

Frequency assignment problem


Type: Frequency assignment
Rating: 3 (intermediate)
Description: Frequency assignment problem: 'abs', 'distance', and 'all-different' constraints; branching strategy for variables; solution callback; interrupting and restarting the search.
File(s): freqasgn.mos, freqasgn_graph.mos


freqasgn.mos
(!****************************************************************
   CP example problems
   ===================
   
   file freqasgn.mos
   `````````````````
   Frequency assignment problem from telecommunications.

   We are given a network of cells (nodes) with requirements of 
   discrete frequency bands. Each cell has a demand of a number of 
   frequencies (bands).
   The objective is to minimize the number of frequencies used in 
   the network so that
   (1) Neighboring nodes all use different frequencies (interference).
   (2) If a cell uses several frequencies they must all be different
       by at least 2.

   *** This model cannot be run with a Community Licence 
       for the provided data instance ***

   (c) 2008 Artelys S.A. and Fair Isaac Corporation
       Creation: 2005, rev. Mar. 2013       
*****************************************************************!)

model "Frequency assignment"
 uses "kalis"
 
 forward public procedure print_solution
  
 declarations
  NODES = 1..10                               ! Range of nodes
  LINKS = 1..18                               ! Range of links between nodes
  DEM: array(NODES) of integer                ! Demand of nodes
  LINK: array(LINKS,1..2) of integer          ! Neighboring nodes 
  INDEX: array(NODES) of integer              ! Start index in 'use' 
  NUMDEM: integer                             ! Upper bound on no. of freq.
 end-declarations

 DEM :: (1..10)[4, 5, 2, 3, 2, 4, 3, 4, 3, 2]
 LINK:: (1..18,1..2)[1, 3, 1, 4, 1, 6, 
                     2, 4, 2, 7, 
                     3, 4, 3, 6, 3, 8, 3, 9,
                     4, 7, 4, 9, 4,10, 
                     5, 7, 5, 8, 5, 9, 
                     6, 9, 7, 8, 8,10]
 NUMDEM:= sum(n in NODES) DEM(n)

! Correspondence of nodes and demand indices:
! use(d) d = 1, ..., DEM(1) correspond to the demands of node 1
!            d = DEM(1)+1, ..., DEM(1)+DEM(2))     - " -     node 2  etc.
 INDEX(1):= 1
 forall(n in NODES | n > 1) INDEX(n) := INDEX(n-1) + DEM(n-1)

 declarations
  DEMANDS = 1..NUMDEM                         ! Range of frequency demands 
  use: array(DEMANDS) of cpvar                ! Frequency used for a demand
  numfreq: cpvar                              ! Number of frequencies used
  Strategy: array(range) of cpbranching
 end-declarations

! Setting the domain of the decision variables
 forall(d in DEMANDS) setdomain(use(d), 1, NUMDEM)

! All frequencies attached to a node must be different by at least 2
 forall(n in NODES, c,d in INDEX(n)..INDEX(n)+DEM(n)-1 | c<d)
  distance(use(c), use(d)) >= 2
!  abs(use(c) - use(d)) >= 2
  
! Neighboring nodes take all-different frequencies
 forall(l in LINKS)
  all_different(
   union(d in INDEX(LINK(l,1))..INDEX(LINK(l,1))+DEM(LINK(l,1))-1) {use(d)} + 
   union(d in INDEX(LINK(l,2))..INDEX(LINK(l,2))+DEM(LINK(l,2))-1) {use(d)},
   KALIS_GEN_ARC_CONSISTENCY)

! Objective function: minimize the number of frequencies used, that is, 
! minimize the largest value assigned to 'use'
 setname(numfreq, "NumFreq")
 numfreq = maximum(use)

! Search strategy
 Strategy(1):=assign_var(KALIS_SMALLEST_DOMAIN, KALIS_MIN_TO_MAX, use)
 Strategy(2):=assign_var(KALIS_MAX_DEGREE, KALIS_MIN_TO_MAX, use)
 cp_set_branching(Strategy(1))
 setparam("KALIS_MAX_COMPUTATION_TIME", 1)
 cp_set_solution_callback("print_solution")

! Try to find solution(s) with strategy 1
 if (cp_minimize(numfreq)) then
  cp_show_stats
  sol:=getsol(numfreq)
 end-if

! Restart search with strategy 2
 cp_reset_search
 if sol>0 then                             ! If a solution was found:
  numfreq <= sol-1                         ! Add upper bound on objective
 end-if
 cp_set_branching(Strategy(2))
 setparam("KALIS_MAX_COMPUTATION_TIME", 1000)

 if (cp_minimize(numfreq)) then
  cp_show_stats
 elif sol>0 then
  writeln("Optimality proven")
 else
  writeln("Problem has no solution")
 end-if

!********************************************************************
! **** Solution printout ****
 public procedure print_solution
  writeln("Number of frequencies: ", getsol(numfreq))
  writeln("Frequency assignment: ")
  forall(n in NODES) do
   write("Node ", n, ": ")
   forall(d in INDEX(n)..INDEX(n)+DEM(n)-1) write(getsol(use(d)), " ")
   writeln
  end-do
 end-procedure

end-model

freqasgn_graph.mos
(!****************************************************************
   CP example problems
   ===================
   
   file freqas_graph.mos
   `````````````````````
   Frequency assignment problem from telecommunications.
   - Solution graph drawing-

   We are given a network of cells (nodes) with requirements of 
   discrete frequency bands. Each cell has a demand of a number of 
   frequencies (bands).
   The objective is to minimize the number of frequencies used in 
   the network so that
   (1) Neighboring nodes all use different frequencies (interference).
   (2) If a cell uses several frequencies they must all be different
       by at least 2.

   *** This model cannot be run with a Community Licence 
       for the provided data instance ***

   (c) 2008 Artelys S.A. and Fair Isaac Corporation
       Creation: 2005, rev. Sep. 2018       
*****************************************************************!)

model "Frequency assignment"
 uses "kalis", "mmsvg"
 
 forward public procedure print_solution
 forward procedure draw_solution
  
 declarations
  NODES = 1..10                               ! Range of nodes
  LINKS = 1..18                               ! Range of links between nodes
  DEM: array(NODES) of integer                ! Demand of nodes
  LINK: array(LINKS,1..2) of integer          ! Neighboring nodes 
  INDEX: array(NODES) of integer              ! Start index in 'use' 
  NUMDEM: integer                             ! Upper bound on no. of freq.
 end-declarations

 DEM :: (1..10)[4, 5, 2, 3, 2, 4, 3, 4, 3, 2]
 LINK:: (1..18,1..2)[1, 3, 1, 4, 1, 6, 
                     2, 4, 2, 7, 
                     3, 4, 3, 6, 3, 8, 3, 9,
                     4, 7, 4, 9, 4,10, 
                     5, 7, 5, 8, 5, 9, 
                     6, 9, 7, 8, 8,10]
 NUMDEM:= sum(n in NODES) DEM(n)

! Correspondence of nodes and demand indices:
! use(d) d = 1, ..., DEM(1) correspond to the demands of node 1
!            d = DEM(1)+1, ..., DEM(1)+DEM(2))     - " -     node 2  etc.
 INDEX(1):= 1
 forall(n in NODES | n > 1) INDEX(n) := INDEX(n-1) + DEM(n-1)

 declarations
  DEMANDS = 1..NUMDEM                         ! Range of frequency demands 
  use: array(DEMANDS) of cpvar                ! Frequency used for a demand
  numfreq: cpvar                              ! Number of frequencies used
  Strategy: array(range) of cpbranching
 end-declarations

! Setting the domain of the decision variables
 forall(d in DEMANDS) setdomain(use(d), 1, NUMDEM)

! All frequencies attached to a node must be different by at least 2
 forall(n in NODES, c,d in INDEX(n)..INDEX(n)+DEM(n)-1 | c<d)
  distance(use(c), use(d)) >= 2
!  abs(use(c) - use(d)) >= 2

! Neighboring nodes take all-different frequencies
 forall(l in LINKS)
  all_different(
   union(d in INDEX(LINK(l,1))..INDEX(LINK(l,1))+DEM(LINK(l,1))-1) {use(d)} + 
   union(d in INDEX(LINK(l,2))..INDEX(LINK(l,2))+DEM(LINK(l,2))-1) {use(d)},
   KALIS_GEN_ARC_CONSISTENCY)

! Objective function: minimize the number of frequencies used, that is, 
! minimize the largest value assigned to 'use'
 setname(numfreq, "NumFreq")
 numfreq = maximum(use)

! Search strategy
 Strategy(1):=assign_var(KALIS_SMALLEST_DOMAIN, KALIS_MIN_TO_MAX, use)
 Strategy(2):=assign_var(KALIS_MAX_DEGREE, KALIS_MIN_TO_MAX, use)
 cp_set_branching(Strategy(1))
 setparam("KALIS_MAX_COMPUTATION_TIME", 1)
 cp_set_solution_callback("print_solution")

! Try to find solution(s) with strategy 1
 if (cp_minimize(numfreq)) then
  draw_solution
  cp_show_stats
  sol:=getsol(numfreq)
 end-if

! Restart search with strategy 2
 cp_reset_search
 if sol>0 then                             ! If a solution was found:
  numfreq <= sol-1                         ! Add upper bound on objective
 end-if
 cp_set_branching(Strategy(2))
 setparam("KALIS_MAX_COMPUTATION_TIME", 1000)

 if (cp_minimize(numfreq)) then
  draw_solution
  cp_show_stats
 elif sol>0 then
  writeln("Optimality proven")
 else
  writeln("Problem has no solution")
 end-if

 svgwaitclose("Close browser window to terminate model execution.", 1)

!********************************************************************
! **** Solution printout ****
 public procedure print_solution
  writeln("Number of frequencies: ", getsol(numfreq))
  writeln("Frequency assignment: ")
  forall(n in NODES) do
   write("Node ", n, ": ")
   forall(d in INDEX(n)..INDEX(n)+DEM(n)-1) write(getsol(use(d)), " ")
   writeln
  end-do
 end-procedure

! **** Solution drawing ****
 procedure draw_solution
  declarations
   GraphFreq: array(range) of integer
   X,Y: array(NODES) of real        ! Coordinates of nodes
  end-declarations 
  
  N:= getsize(NODES)
  forall(n in NODES) do
   X(n):= N/2*(cos(M_PI/3+1.2*n*M_PI/N))
   Y(n):= (getsol(numfreq)+1)/2*(1+sin(M_PI/3+1.2*n*M_PI/N))
  end-do
  
 ! Draw different color graph per frequency 
  forall (f in 1..getsol(numfreq)) do
   svgaddgroup("G"+f, "Frequency "+f)
   svgaddtext(3, f, "Freq "+f)
  end-do
  forall(n in NODES, d in INDEX(n)..INDEX(n)+DEM(n)-1)
   svgaddline("G"+getsol(use(d)), X(n), Y(n), 3, getsol(use(d)))
 
 ! Graph representing nodes and links between nodes 
  svgaddgroup("N", "Network", SVG_BLACK)
  svgsetstyle("text-anchor", "end")
  forall(l in LINKS) 
   svgaddline(X(LINK(l,1)), Y(LINK(l,1)), X(LINK(l,2)), Y(LINK(l,2)))
  forall(n in NODES) svgaddtext(X(n),Y(n), "Node "+n)

  svgsetgraphviewbox(-N/2-2,-1,N+5,N+5)
  svgsetgraphscale(25)
  svgrefresh
 end-procedure

end-model

© 2001-2020 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.