
#-------------------------------------------------------------------------------
# Module:     fileExport.tk
# Activation: Dynamically loaded on user request
# Scope:      Export filters for graph objects
#-------------------------------------------------------------------------------



proc goblinExport {object fileName format} {

    # Native GOBLIN Format
	
	if {[string equal $format "gob"]} {
        goblin write $object $fileName
		return
    }
	
	
    if {[$object is mip]} {

        # Standard MPS Format

	    if {[string equal $format "mps"]} {
            $object write mps $fileName
		    return
        }

        # CPLEX MPS Format

	    if {[string equal $format "cplex"]} {
            $object write cplex $fileName
		    return
        }

        # CPLEX LP Format

	    if {[string equal $format "lp"]} {
            $object write lp $fileName
		    return
        }

        # CPLEX MPS Basis

	    if {[string equal $format "bas"]} {
            $object write bas $fileName
		    return
        }
	
	    error "Unknown Format: $format"
	}
	
    # Tcl Library Format
	
	if {[string equal $format "tcl"]} {
		set file [open "$fileName" w]

		puts $file "package require Tcl"
		puts $file "package require struct"
		puts $file "::struct::graph \$gobName"

        for {set v 0} {$v<[$object #nodes]} {incr v} {
            puts $file ""
		    puts $file "\$gobName node insert $v"
            if {![$object constant demand]} {
    		    puts $file "\$gobName node set $v -key demand\
                    [$object node $v demand]"
            }
            if {[$object max cx]>0} {
    		    puts $file "\$gobName node set $v -key cx\
                    [$object node $v cx]"
            }
            if {[$object max cy]>0} {
    		    puts $file "\$gobName node set $v -key cy\
                    [$object node $v cy]"
            }
    	}

        for {set a 0} {$a<[$object #arcs]} {incr a} {
            set a2 [expr {2*$a}]
            puts $file ""
            puts $file "\$gobName arc insert\
                [$object arc $a2 tail] [$object arc $a2 head] $a"
            if {![$object is directed] && ![$object is undirected]} {
                puts $file "\$gobName arc set $a -key orientation\
                    [$object arc $a2 orientation]"
            }
            if {![$object constant length]} {
    		    puts $file "\$gobName arc set $a -key length\
                    [$object arc $a2 length]"
            }
            if {![$object constant ucap]} {
    		    puts $file "\$gobName arc set $a -key ucap\
                    [$object arc $a2 ucap]"
            }
            if {![$object constant lcap]} {
    		    puts $file "\$gobName arc set $a -key lcap\
                    [$object arc $a2 lcap]"
            }
    	}

		close $file
		return
    }
	
	
	# DIMACS Formats

    if {[string equal $format "edge"]} {
		set file [open "$fileName" w]

		puts $file "p edge [$object #nodes] [$object #arcs]"
        for {set a 0} {$a<[$object #arcs]} {incr a} {
		    puts $file "e \
                [expr [$object arc [expr {2*$a}] tail]+1] \
                [expr [$object arc [expr {2*$a}] head]+1] \
                [$object arc [expr {2*$a}] length]"
    	}

		close $file
		return
	}

    if {[string equal $format "max"]} {
		global goblinSource goblinTarget

		set file [open "$fileName" w]

		puts $file "p max [$object #nodes] [$object #arcs]"
		puts $file "n [expr $goblinSource+1] s"
		puts $file "n [expr $goblinTarget+1] t"
        for {set a 0} {$a<[$object #arcs]} {incr a} {
		    puts $file "a \
                [expr [$object arc [expr {2*$a}] tail]+1] \
                [expr [$object arc [expr {2*$a}] head]+1] \
                [$object arc [expr {2*$a}] ucap]"
    	}

		close $file
		return
    }

    if {[string equal $format "min"]} {
		set file [open "$fileName" w]

		puts $file "p min [$object #nodes] [$object #arcs]"
        for {set v 0} {$v<[$object #nodes]} {incr v} {
            if {[$object node $v demand]!=0} {
		        puts $file "n [expr $v+1] [expr -[$object node $v demand]]"
            }
    	}
        for {set a 0} {$a<[$object #arcs]} {incr a} {
		    puts $file "a \
                [expr [$object arc [expr {2*$a}] tail]+1] \
                [expr [$object arc [expr {2*$a}] head]+1] \
                [$object arc [expr {2*$a}] lcap] \
                [$object arc [expr {2*$a}] ucap] \
                [$object arc [expr {2*$a}] length]"
    	}

		close $file
		return
    }

    if {[string equal $format "asn"]} {
		set file [open "$fileName" w]

		puts $file "p asn [$object #nodes] [$object #arcs]"
        for {set v 0} {$v<[$object #outer]} {incr v} {
		    puts $file "n [expr $v+1] s"
    	}
        for {set a 0} {$a<[$object #arcs]} {incr a} {
		    puts $file "a \
                [expr [$object arc [expr {2*$a}] tail]+1] \
                [expr [$object arc [expr {2*$a}] head]+1] \
                [$object arc [expr {2*$a}] length]"
    	}

		close $file
		return
	}

    if {[string equal $format "flow"]} {
		set file [open "$fileName" w]

		puts $file "s [expr int([$object weight])]"

        for {set a 0} {$a<[$object #arcs]} {incr a} {
		    puts $file "f \
                [expr [$object arc [expr {2*$a}] tail]+1] \
                [expr [$object arc [expr {2*$a}] head]+1] \
                [$object arc [expr {2*$a}] subgraph]"
    	}

		close $file
		return
    }

    if {[string equal $format "geom"]} {
		set file [open "$fileName" w]

		puts $file "p min [$object #nodes] 2"
        for {set v 0} {$v<[$object #nodes]} {incr v} {
            if {[$object node $v demand]!=0} {
		        puts $file "n [expr $v+1] [$object node $v cx] [$object node $v cy]"
            }
    	}

		close $file
		return
    }

    if {[string equal $format "match"]} {
		set file [open "$fileName" w]

		puts $file "s [expr int([$object weight])]"

        for {set a 0} {$a<[$object #arcs]} {incr a} {
            if {[$object arc [expr {2*$a}] subgraph]>0} {
		        puts $file "m \
                    [expr [$object arc [expr {2*$a}] tail]+1] \
                    [expr [$object arc [expr {2*$a}] head]+1]"
            }
    	}

		close $file
		return
    }


	# TSPLIB Formats

    if {[string equal $format "tsp"]} {
        if {[$object is undirected] && ![$object is sparse]} {
		    set file [open "$fileName" w]

		    puts $file "NAME : [file tail $fileName]"
		    puts $file "COMMENT : File generated by GOBLIN"
		    puts $file "TYPE : TSP"
		    puts $file "DIMENSION : [$object #nodes]"

            global goblinMethGeometry
            if {$goblinMethGeometry==0} {
                puts $file "EDGE_WEIGHT_TYPE : EXPLICIT"
                puts $file "EDGE_WEIGHT_FORMAT : UPPER_ROW"
                if {[$object max cx]>0 || [$object max cx]>0} {
                    puts $file "DISPLAY_DATA_TYPE : TWOD_DISPLAY"
                }

		        puts $file "EDGE_WEIGHT_SECTION"
                for {set i 0} {$i<[expr [$object #nodes]-1]} {incr i} {
                    for {set j [expr $i+1]} {$j<[$object #nodes]} {incr j} {
                        puts -nonewline $file "[$object arc [$object adjacency $i $j] length] "
                    }
                    puts $file ""
                }
                
                if {[$object max cx]>0 || [$object max cx]>0} {
        		    puts $file "DISPLAY_DATA_SECTION"
                    for {set v 0} {$v<[$object #nodes]} {incr v} {
		                puts $file "[expr $v+1] [$object node $v cx] [$object node $v cy]"
                    }
                }

        		puts $file "EOF"
    		    close $file
	    	    return
            }
            
            if {$goblinMethGeometry==1} {puts $file "EDGE_WEIGHT_TYPE : MAN_2D"}
            if {$goblinMethGeometry==2} {puts $file "EDGE_WEIGHT_TYPE : EUC_2D"}
            if {$goblinMethGeometry==3} {puts $file "EDGE_WEIGHT_TYPE : MAX_2D"}
            if {$goblinMethGeometry==4} {puts $file "EDGE_WEIGHT_TYPE : GEO"}
		    puts $file "NODE_COORD_SECTION"
            for {set v 0} {$v<[$object #nodes]} {incr v} {
		        puts $file "[expr $v+1] [$object node $v cx] [$object node $v cy]"
            }
        
    		puts $file "EOF"

		    close $file
		    return
        }
        
        if {[$object is directed] && ![$object is sparse]} {
		    set file [open "$fileName" w]

		    puts $file "NAME : [file tail $fileName]"
		    puts $file "COMMENT : File generated by GOBLIN"
		    puts $file "TYPE : ATSP"
		    puts $file "DIMENSION : [$object #nodes]"
            puts $file "EDGE_WEIGHT_TYPE : EXPLICIT"
            puts $file "EDGE_WEIGHT_FORMAT : FULL_MATRIX"
            if {[$object max cx]>0 || [$object max cx]>0} {
                puts $file "DISPLAY_DATA_TYPE : TWOD_DISPLAY"
            }

	        puts $file "EDGE_WEIGHT_SECTION"
            for {set i 0} {$i<[$object #nodes]} {incr i} {
                for {set j 0} {$j<[$object #nodes]} {incr j} {
                    puts -nonewline $file "[$object arc [$object adjacency $i $j] length] "
                }
                puts $file ""
            }
                
            if {[$object max cx]>0 || [$object max cx]>0} {
                puts $file "DISPLAY_DATA_SECTION"
                for {set v 0} {$v<[$object #nodes]} {incr v} {
                    puts $file "[expr $v+1] [$object node $v cx] [$object node $v cy]"
                }
            }
        
    		puts $file "EOF"

		    close $file
		    return
        }
        
        error "Graph type is not supported"
    }

    if {[string equal $format "tour"]} {
		set file [open "$fileName" w]

		puts $file "NAME : [file tail $fileName]"
		puts $file "TYPE : TOUR"
		puts $file "COMMENT : Generated by GOBLIN (Objective [expr int([$object length])])"
		puts $file "DIMENSION : [$object #nodes]"
		puts $file "TOUR_SECTION"
        
        set v 0
        set w -1
        while {$w!=0} {
            puts $file [expr $v+1]
            for {set w 0} {[$object arc [$object node $w predecessor] tail]!= $v} {incr w} {}
            set v [$object arc [$object node $w predecessor] head]
        }
		puts $file "-1"
		puts $file "EOF"

		close $file
		return
    }
	
	error "Unknown Format: $format"
}
                    
