alpar@174: /* -*- C++ -*- alpar@174: * alpar@174: * This file is a part of LEMON, a generic C++ optimization library alpar@174: * alpar@174: * Copyright (C) 2003-2006 alpar@174: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@174: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@174: * alpar@174: * Permission to use, modify and distribute this software is granted alpar@174: * provided that this copyright notice appears in all copies. For alpar@174: * precise terms see the accompanying LICENSE file. alpar@174: * alpar@174: * This software is provided "AS IS" with no warranty of any kind, alpar@174: * express or implied, and with no claim as to its suitability for any alpar@174: * purpose. alpar@174: * alpar@174: */ alpar@174: hegyi@42: #include hegyi@42: hegyi@42: bool NewMapWin::closeIfEscapeIsPressed(GdkEventKey* e) hegyi@42: { hegyi@42: if(e->keyval==GDK_Escape) hegyi@42: { hegyi@42: hide(); hegyi@42: } hegyi@42: return true; hegyi@42: } hegyi@42: hegyi@96: NewMapWin::NewMapWin(const std::string& title, NoteBookTab & mw, bool itisedge, bool edgenode):Gtk::Dialog(title, true, true),mytab(mw),node("Create NodeMap"),edge("Create EdgeMap") hegyi@42: { hegyi@42: set_default_size(200, 50); hegyi@42: hegyi@42: signal_key_press_event().connect(sigc::mem_fun(*this, &NewMapWin::closeIfEscapeIsPressed)); hegyi@42: hegyi@90: Gtk::VBox * vbox=get_vbox(); hegyi@42: hegyi@42: //entries hegyi@42: table=new Gtk::Table(3, 2, false); hegyi@42: hegyi@42: label=new Gtk::Label; hegyi@42: label->set_text("Name of new map:"); hegyi@42: name.set_text(""); hegyi@42: hegyi@42: (*table).attach(*label,0,1,0,1,Gtk::SHRINK,Gtk::SHRINK,10,3); hegyi@42: (*table).attach(name,1,2,0,1,Gtk::SHRINK,Gtk::SHRINK,10,3); hegyi@42: hegyi@42: label=new Gtk::Label; hegyi@42: label->set_text("Default value in the map:"); hegyi@42: default_value.set_text("0"); hegyi@42: hegyi@42: (*table).attach(*label,0,1,1,2,Gtk::SHRINK,Gtk::SHRINK,10,3); hegyi@42: (*table).attach(default_value,1,2,1,2,Gtk::SHRINK,Gtk::SHRINK,10,3); hegyi@42: hegyi@42: //node vs. edge map selector hegyi@42: Gtk::RadioButton::Group group = node.get_group(); hegyi@42: edge.set_group(group); hegyi@90: hegyi@90: if(edgenode) hegyi@90: { hegyi@90: (*table).attach(node,0,1,2,3,Gtk::SHRINK,Gtk::SHRINK,10,3); hegyi@90: (*table).attach(edge,1,2,2,3,Gtk::SHRINK,Gtk::SHRINK,10,3); hegyi@90: } hegyi@90: else hegyi@90: { hegyi@90: if(itisedge) hegyi@90: { hegyi@90: edge.set_active(); hegyi@90: } hegyi@90: else hegyi@90: { hegyi@90: node.set_active(); hegyi@90: } hegyi@90: } hegyi@42: hegyi@90: vbox->pack_start(*table); hegyi@42: hegyi@42: //OK button hegyi@90: add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK); hegyi@42: hegyi@42: show_all_children(); hegyi@42: hegyi@42: } hegyi@42: hegyi@90: void NewMapWin::on_response(int response_id) hegyi@85: { hegyi@90: if(response_id==Gtk::RESPONSE_OK) hegyi@85: { hegyi@90: double def_val=0; hegyi@85: hegyi@90: //get and formulate text hegyi@90: std::string def_val_str=default_value.get_text(); hegyi@118: hegyi@118: bool only_nums=true; hegyi@118: for(int i=0;i<(int)def_val_str.size() && only_nums;i++) hegyi@118: { hegyi@118: if( def_val_str[i]<'0' || def_val_str[i]>'9' ) hegyi@118: { hegyi@118: only_nums=false; hegyi@118: } hegyi@118: } hegyi@118: std::string polishform; hegyi@118: hegyi@118: if(only_nums) hegyi@118: { hegyi@118: def_val=atof(def_val_str.c_str()); hegyi@118: } hegyi@118: else hegyi@118: { hegyi@118: polishform=string2Polishform(def_val_str,edge.get_active()); hegyi@118: } hegyi@42: hegyi@90: //get name of text hegyi@90: std::string mapname=name.get_text(); hegyi@118: hegyi@118: if(!mapname.empty()&&(!polishform.empty()||only_nums)) hegyi@90: { hegyi@90: int abortion=0; hegyi@90: if(edge.get_active()) hegyi@90: { hegyi@90: //create the new map hegyi@118: Graph::EdgeMap * emptr=new Graph::EdgeMap (mytab.mapstorage.graph, def_val); hegyi@118: hegyi@118: if(!only_nums) hegyi@88: { hegyi@118: std::stack polishstack; hegyi@118: hegyi@118: for(EdgeIt k(mytab.mapstorage.graph); k!=INVALID; ++k) hegyi@88: { hegyi@118: for(int i=0;i<(int)polishform.size();i++) hegyi@88: { hegyi@118: double op1=0, op2=0; hegyi@118: bool operation=true; hegyi@90: switch(polishform[i]) hegyi@90: { hegyi@90: case '+': hegyi@90: case '-': hegyi@90: case '/': hegyi@90: case '*': hegyi@118: op1=polishstack.top(); hegyi@118: polishstack.pop(); hegyi@118: op2=polishstack.top(); hegyi@118: polishstack.pop(); hegyi@90: break; hegyi@90: default: hegyi@118: //substitute variable hegyi@118: std::map< std::string,Graph::EdgeMap * > ems=mytab.mapstorage.edgemap_storage; hegyi@118: bool itisvar=(ems.find(ch2var[ polishform[i] ])!=ems.end()); hegyi@118: if(itisvar) hegyi@118: { hegyi@118: polishstack.push( (*(mytab.mapstorage.edgemap_storage[ ch2var[ polishform[i] ] ]))[k]); hegyi@118: } hegyi@118: else hegyi@118: { hegyi@118: polishstack.push(atof(ch2var[ polishform[i] ].c_str())); hegyi@118: } hegyi@118: operation=false; hegyi@90: break; hegyi@90: } hegyi@118: if(operation) hegyi@118: { hegyi@118: double res; hegyi@118: switch(polishform[i]) hegyi@118: { hegyi@118: case '+': hegyi@118: res=op1+op2; hegyi@118: break; hegyi@118: case '-': hegyi@118: res=op2-op1; hegyi@118: break; hegyi@118: case '/': hegyi@118: res=op2/op1; hegyi@118: break; hegyi@118: case '*': hegyi@118: res=op1*op2; hegyi@118: break; hegyi@118: default: hegyi@118: std::cout << "How could we get here?" << std::endl; hegyi@118: break; hegyi@118: } hegyi@118: polishstack.push(res); hegyi@118: } hegyi@118: }//foreach letter in polishform hegyi@118: (*emptr)[k]=polishstack.top(); hegyi@118: }//foreach edge hegyi@118: }//!only_nums hegyi@90: hegyi@90: //if addition was not successful addEdgeMap returns one. hegyi@90: //cause can be that there is already a map named like the new one hegyi@96: if(mytab.mapstorage.addEdgeMap(mapname, emptr, def_val)) hegyi@90: { hegyi@90: abortion=1; hegyi@90: } hegyi@90: hegyi@90: //add it to the list of the displayable maps hegyi@108: //furthermore it is done by signals hegyi@108: //mytab.registerNewEdgeMap(mapname); hegyi@90: hegyi@90: //display it hegyi@94: //gdc.changeEdgeText(mapname); hegyi@88: } hegyi@90: else //!edge.get_active() hegyi@90: { hegyi@90: //create the new map hegyi@118: Graph::NodeMap * emptr=new Graph::NodeMap (mytab.mapstorage.graph, def_val); hegyi@88: hegyi@118: if(!only_nums) hegyi@118: { hegyi@118: std::stack polishstack; hegyi@88: hegyi@118: for(NodeIt k(mytab.mapstorage.graph); k!=INVALID; ++k) hegyi@88: { hegyi@118: for(int i=0;i<(int)polishform.size();i++) hegyi@88: { hegyi@118: double op1=0, op2=0; hegyi@118: bool operation=true; hegyi@90: switch(polishform[i]) hegyi@90: { hegyi@90: case '+': hegyi@90: case '-': hegyi@90: case '/': hegyi@90: case '*': hegyi@118: op1=polishstack.top(); hegyi@118: polishstack.pop(); hegyi@118: op2=polishstack.top(); hegyi@118: polishstack.pop(); hegyi@90: break; hegyi@90: default: hegyi@118: std::map< std::string,Graph::NodeMap * > nms=mytab.mapstorage.nodemap_storage; hegyi@118: bool itisvar=(nms.find(ch2var[ polishform[i] ])!=nms.end()); hegyi@118: if(itisvar) hegyi@118: { hegyi@118: polishstack.push( (*(mytab.mapstorage.nodemap_storage[ ch2var[ polishform[i] ] ]))[k]); hegyi@118: } hegyi@118: else hegyi@118: { hegyi@118: polishstack.push(atof(ch2var[ polishform[i] ].c_str())); hegyi@118: } hegyi@118: operation=false; hegyi@90: break; hegyi@90: } hegyi@118: if(operation) hegyi@118: { hegyi@118: double res; hegyi@118: switch(polishform[i]) hegyi@118: { hegyi@118: case '+': hegyi@118: res=op1+op2; hegyi@118: break; hegyi@118: case '-': hegyi@118: res=op2-op1; hegyi@118: break; hegyi@118: case '/': hegyi@118: res=op2/op1; hegyi@118: break; hegyi@118: case '*': hegyi@118: res=op1*op2; hegyi@118: break; hegyi@118: default: hegyi@118: std::cout << "How could we get here?" << std::endl; hegyi@118: break; hegyi@118: } hegyi@118: polishstack.push(res); hegyi@118: } hegyi@90: } hegyi@118: (*emptr)[k]=polishstack.top(); hegyi@88: } hegyi@88: } hegyi@90: //if addition was not successful addNodeMap returns one. hegyi@90: //cause can be that there is already a map named like the new one hegyi@96: if(mytab.mapstorage.addNodeMap(mapname,emptr, def_val)) hegyi@90: { hegyi@90: abortion=1; hegyi@90: } hegyi@90: hegyi@90: //add it to the list of the displayable maps hegyi@108: //furthermore it is done by signals hegyi@108: //mytab.registerNewNodeMap(mapname); hegyi@90: hegyi@90: //display it hegyi@90: //gdc.changeNodeText(mapname); hegyi@88: } hegyi@90: if(!abortion) hegyi@88: { hegyi@90: name.set_text(""); hegyi@90: default_value.set_text("0"); hegyi@90: edge.show(); hegyi@90: node.show(); hegyi@90: hide(); hegyi@88: } hegyi@46: } hegyi@42: } hegyi@42: } hegyi@42: hegyi@90: hegyi@88: std::string NewMapWin::string2Polishform(std::string rawcommand, bool itisedge) hegyi@88: { hegyi@88: bool valid_entry=true; hegyi@88: hegyi@88: std::map str2i; hegyi@88: hegyi@88: std::string command; hegyi@88: hegyi@88: std::string variable; hegyi@88: hegyi@88: char index='a'; hegyi@88: hegyi@88: for(int i=0;(valid_entry&&(i<(int)rawcommand.size()));i++) hegyi@88: { hegyi@88: switch(rawcommand[i]) hegyi@88: { hegyi@88: case '+': hegyi@88: case '-': hegyi@88: case '*': hegyi@88: case '/': hegyi@88: case ')': hegyi@88: case '(': hegyi@88: if(!variable.empty()) hegyi@88: { hegyi@88: valid_entry=validVariable(variable, itisedge); hegyi@88: ch2var[index]=variable; hegyi@88: command+=index; hegyi@88: index++; hegyi@88: variable.erase(0,variable.size()); hegyi@88: } hegyi@88: command+=rawcommand[i]; hegyi@88: break; hegyi@88: default: hegyi@88: variable+=rawcommand[i]; hegyi@88: break; hegyi@88: } hegyi@88: } hegyi@88: hegyi@88: if(!variable.empty()&&valid_entry) hegyi@88: { hegyi@88: valid_entry=validVariable(variable, itisedge); hegyi@88: ch2var[index]=variable; hegyi@88: command+=index; hegyi@88: index++; hegyi@88: variable.erase(0,variable.size()); hegyi@88: } hegyi@88: hegyi@88: if(valid_entry) hegyi@88: { hegyi@88: unsigned int pr=10000; hegyi@88: bool prevmult=false; hegyi@89: unsigned int prev_change=pr; hegyi@89: unsigned int prev_br=pr; hegyi@88: int counter=0; hegyi@88: std::string comm_nobr=""; hegyi@88: std::vector p; hegyi@88: p.resize(counter+1); hegyi@88: hegyi@88: //limits hegyi@88: //6 brackets embedded hegyi@88: //100 operation in a row from the same priority hegyi@88: hegyi@88: for(int i=0;i<(int)command.size();i++) hegyi@88: { hegyi@88: bool put_in_string=true; hegyi@88: switch(command[i]) hegyi@88: { hegyi@88: case '(': hegyi@88: pr=prev_br+10000; hegyi@88: prev_br=pr; hegyi@88: prevmult=false; hegyi@88: put_in_string=false; hegyi@88: break; hegyi@88: case ')': hegyi@88: pr=prev_br-10000; hegyi@88: prev_br=pr; hegyi@88: prevmult=false; hegyi@88: put_in_string=false; hegyi@88: break; hegyi@88: case '+': hegyi@88: case '-': hegyi@88: if(prevmult) hegyi@88: { hegyi@88: pr=prev_change; hegyi@88: } hegyi@88: p[counter]=pr; hegyi@88: pr-=100; hegyi@88: hegyi@88: prevmult=false; hegyi@88: break; hegyi@88: case '/': hegyi@88: case '*': hegyi@88: if(!prevmult) hegyi@88: { hegyi@88: prev_change=pr; hegyi@88: pr+=200; hegyi@88: pr-=1; hegyi@88: } hegyi@88: p[counter]=pr; hegyi@88: pr-=1; hegyi@88: prevmult=true; hegyi@88: break; hegyi@88: default: hegyi@88: p[counter]=65000; hegyi@88: break; hegyi@88: } hegyi@88: if(put_in_string) hegyi@88: { hegyi@88: counter++; hegyi@88: p.resize(counter+1); hegyi@88: comm_nobr=comm_nobr+command[i]; hegyi@88: } hegyi@88: } hegyi@88: hegyi@88: tree_node * root=weightedString2Tree(comm_nobr, p, 0); hegyi@88: hegyi@88: std::string polishform=postOrder(root); hegyi@88: hegyi@117: deleteTree(root); hegyi@117: hegyi@88: return polishform; hegyi@88: } hegyi@88: return ""; hegyi@88: } hegyi@88: hegyi@117: void NewMapWin::deleteTree(NewMapWin::tree_node * node) hegyi@117: { hegyi@117: if(node->left_child!=NULL) hegyi@117: { hegyi@117: deleteTree(node->left_child); hegyi@117: } hegyi@117: if(node->right_child!=NULL) hegyi@117: { hegyi@117: deleteTree(node->right_child); hegyi@117: } hegyi@117: delete node; hegyi@117: } hegyi@117: hegyi@88: NewMapWin::tree_node * NewMapWin::weightedString2Tree(std::string to_tree, std::vector & p, int offset) hegyi@88: { hegyi@89: unsigned int min=p[offset]; hegyi@88: int minplace=0; hegyi@88: for(int i=0;i<(int)to_tree.size();i++) hegyi@88: { hegyi@88: if(min>p[offset+i]) hegyi@88: { hegyi@88: min=p[offset+i]; hegyi@88: minplace=i; hegyi@88: } hegyi@88: } hegyi@88: tree_node * act_node=new tree_node; hegyi@88: act_node->ch=to_tree[minplace]; hegyi@88: if(to_tree.size()>=3) hegyi@88: { hegyi@88: act_node->left_child=weightedString2Tree(to_tree.substr(0,minplace), p, offset); hegyi@88: act_node->right_child=weightedString2Tree(to_tree.substr(minplace+1,to_tree.size()-minplace-1), p, offset+minplace+1); hegyi@88: } hegyi@88: else hegyi@88: { hegyi@88: act_node->left_child=NULL; hegyi@88: act_node->right_child=NULL; hegyi@88: } hegyi@88: return act_node; hegyi@88: } hegyi@88: hegyi@88: std::string NewMapWin::postOrder(tree_node * subtree) hegyi@88: { hegyi@88: std::string subtree_to_string; hegyi@88: if(subtree->left_child) hegyi@88: { hegyi@88: subtree_to_string=postOrder(subtree->left_child); hegyi@88: } hegyi@88: if(subtree->right_child) hegyi@88: { hegyi@88: subtree_to_string=subtree_to_string+postOrder(subtree->right_child); hegyi@88: } hegyi@88: subtree_to_string=subtree_to_string+subtree->ch; hegyi@88: return subtree_to_string; hegyi@88: } hegyi@88: hegyi@88: bool NewMapWin::validVariable(std::string variable, bool itisedge) hegyi@88: { hegyi@88: bool cancel; hegyi@88: //is it mapname? hegyi@88: if(itisedge) hegyi@88: { hegyi@96: cancel=(mytab.mapstorage.edgemap_storage.find(variable)==mytab.mapstorage.edgemap_storage.end()); hegyi@88: } hegyi@88: else hegyi@88: { hegyi@96: cancel=(mytab.mapstorage.nodemap_storage.find(variable)==mytab.mapstorage.nodemap_storage.end()); hegyi@88: } hegyi@88: //maybe it is number hegyi@88: int point_num=0; hegyi@88: if(cancel) hegyi@88: { hegyi@88: cancel=false; hegyi@88: for(int j=0;(!cancel)&&(j<(int)variable.size());j++) hegyi@88: { hegyi@88: if(((variable[j]<'0')||(variable[j]>'9'))&&(variable[j]!='.')) hegyi@88: { hegyi@88: cancel=true; hegyi@88: } hegyi@88: else hegyi@88: { hegyi@88: if(variable[j]=='.') hegyi@88: { hegyi@88: point_num++; hegyi@88: if(point_num>1) hegyi@88: { hegyi@88: cancel=true; hegyi@88: } hegyi@88: } hegyi@88: } hegyi@88: } hegyi@88: } hegyi@88: if(cancel) hegyi@88: { hegyi@88: return false; hegyi@88: } hegyi@88: return true; hegyi@88: }