diff --git a/IncrementalMinimization/lib/java-cup-11b-runtime.jar b/IncrementalMinimization/lib/java-cup-11b-runtime.jar new file mode 100644 index 00000000..6f02157d Binary files /dev/null and b/IncrementalMinimization/lib/java-cup-11b-runtime.jar differ diff --git a/IncrementalMinimization/lib/java-cup-11b.jar b/IncrementalMinimization/lib/java-cup-11b.jar new file mode 100644 index 00000000..f065a728 Binary files /dev/null and b/IncrementalMinimization/lib/java-cup-11b.jar differ diff --git a/IncrementalMinimization/lib/symbolicautomata.jar b/IncrementalMinimization/lib/symbolicautomata.jar index 67796227..b010cc4d 100644 Binary files a/IncrementalMinimization/lib/symbolicautomata.jar and b/IncrementalMinimization/lib/symbolicautomata.jar differ diff --git a/IncrementalMinimization/preliminary_data.ods b/IncrementalMinimization/preliminary_data.ods new file mode 100644 index 00000000..a45f705d Binary files /dev/null and b/IncrementalMinimization/preliminary_data.ods differ diff --git a/IncrementalMinimization/src/IncrementalMinimization.java b/IncrementalMinimization/src/IncrementalMinimization.java index 9388cdd5..3a8221a6 100644 --- a/IncrementalMinimization/src/IncrementalMinimization.java +++ b/IncrementalMinimization/src/IncrementalMinimization.java @@ -59,7 +59,7 @@ private List> findNonDisjointMoves(Collection pair = Arrays.asList(p, q); //Should already be normalized + List pair = normalize(p,q); //Should already be normalized if (neq.contains(pair)) { return false; @@ -174,7 +174,6 @@ else if(equivClasses.find(p) == equivClasses.find(q)) //Already found p,q equivalent continue; } - //TODO: look into efficiency of HashSet operations, ideally should be O(1) for searching, inserting, removing HashSet> equiv = new HashSet>(num_pairs,1); HashSet> path = new HashSet>(num_pairs,1); @@ -216,7 +215,8 @@ else if(equivClasses.find(p) == equivClasses.find(q)) } } Integer newInitialState = equivClasses.find(aut.getInitialState()); - return SFA.MkSFA(newTransitions, newInitialState, newFinalStates, ba); + SFA minAut = SFA.MkSFA(newTransitions, newInitialState, newFinalStates, ba, false); + return minAut; } } diff --git a/IncrementalMinimization/src/TestIncrementalMinimization.java b/IncrementalMinimization/src/TestIncrementalMinimization.java index 01363d50..55dcfd6c 100644 --- a/IncrementalMinimization/src/TestIncrementalMinimization.java +++ b/IncrementalMinimization/src/TestIncrementalMinimization.java @@ -1,5 +1,10 @@ import static org.junit.Assert.*; +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedList; @@ -9,16 +14,23 @@ import org.junit.Test; import org.sat4j.specs.TimeoutException; +import com.google.common.base.Stopwatch; + +import benchmark.SFAprovider; + import theory.BooleanAlgebra; +import theory.characters.CharPred; +import theory.characters.StdCharPred; import theory.intervals.IntPred; import theory.intervals.IntegerSolver; +import theory.intervals.UnaryCharIntervalSolver; import automata.sfa.SFA; import automata.sfa.SFAInputMove; import automata.sfa.SFAMove; public class TestIncrementalMinimization { - @Test + //@Test public void testMyAut() throws TimeoutException { //our algebra is constructed IntegerSolver ba = new IntegerSolver(); @@ -80,6 +92,88 @@ public void testMyAut() throws TimeoutException { //SFA that the library computes } - //TODO: add more tests both for correctness and for speed + @Test + public void testCharPred() throws TimeoutException + { + UnaryCharIntervalSolver ba = new UnaryCharIntervalSolver(); + CharPred alphaLower = StdCharPred.LOWER_ALPHA; + CharPred alphaAll = StdCharPred.ALPHA; + CharPred a = new CharPred('a'); + CharPred num = StdCharPred.NUM; + CharPred comma = new CharPred(','); + + Collection> transitions = new LinkedList>(); + transitions.add(new SFAInputMove(0,0,a)); + CharPred lowerNotA = ba.MkAnd(alphaLower, ba.MkNot(a)); + transitions.add(new SFAInputMove(0,1,lowerNotA)); + transitions.add(new SFAInputMove(1,0,alphaLower)); + transitions.add(new SFAInputMove(0,2,num)); + transitions.add(new SFAInputMove(1,2,num)); + transitions.add(new SFAInputMove(2,3,comma)); + transitions.add(new SFAInputMove(3,4,alphaLower)); + transitions.add(new SFAInputMove(3,1,num)); + transitions.add(new SFAInputMove(4,3,lowerNotA)); + transitions.add(new SFAInputMove(4,4,a)); + transitions.add(new SFAInputMove(4,0,num)); + + SFA aut = SFA.MkSFA(transitions, 0, Arrays.asList(3,4), ba); + aut = aut.determinize(ba).mkTotal(ba); + + SFA incrMinAut = IncrementalMinimization.incrementalMinimize(aut, ba); + SFA stdMinAut = aut.minimize(ba); + Assert.assertTrue(incrMinAut.isDeterministic(ba)); + Assert.assertTrue(SFA.areEquivalent(incrMinAut,stdMinAut,ba)); + Assert.assertTrue(incrMinAut.stateCount() <= stdMinAut.stateCount()); + } + + @Test + public void testRegEx() throws TimeoutException, IOException + { + //import list of regex. Heavily borrowed code from symbolic automata library + FileReader regexFile = new FileReader("src/pattern@75.txt"); + BufferedReader read = new BufferedReader(regexFile); + ArrayList regexList = new ArrayList(); + String line; + while(true) + { + line = read.readLine(); + if (line == null) + { + break; + } + regexList.add(line); + } + //regex converted to SFAs and minimized + UnaryCharIntervalSolver ba = new UnaryCharIntervalSolver(); + System.out.println(regexList.size()); + ArrayList messageList = new ArrayList(); + for (String regex : regexList) + { + SFA aut = (new SFAprovider(regex, ba)).getSFA(); + if (aut.stateCount() > 200) //Disjoint Set data structure not optimized for large state space, TODO optimize + { + continue; + } + long incrStart = System.nanoTime(); + SFA incrMinAut = IncrementalMinimization.incrementalMinimize(aut, ba); + Double incrTime = ((double)(System.nanoTime() - incrStart)/1000); + long stdStart = System.nanoTime(); + SFA stdMinAut = aut.minimize(ba); + Double stdTime = ((double)(System.nanoTime() - stdStart)/1000); + Assert.assertTrue(incrMinAut.isDeterministic(ba)); + Assert.assertTrue(SFA.areEquivalent(incrMinAut, stdMinAut, ba)); + Assert.assertTrue(incrMinAut.stateCount() <= stdMinAut.stateCount()); + String initialStateCount = Integer.toString(aut.stateCount()); + String finalStateCount = Integer.toString(stdMinAut.stateCount()); + String message = "states: " + initialStateCount + " -> " + finalStateCount + ", " + + "incremental time: " + Double.toString(incrTime) + ", Standard time: " + + Double.toString(stdTime) + " (microsecs)"; + messageList.add(message); + } + for (String msg : messageList) + { + System.out.println(msg); + } + } } diff --git a/IncrementalMinimization/src/pattern@75.txt b/IncrementalMinimization/src/pattern@75.txt new file mode 100644 index 00000000..dd4d9132 --- /dev/null +++ b/IncrementalMinimization/src/pattern@75.txt @@ -0,0 +1,75 @@ +^[0-9]*[a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([a-zA-Z][-\w\.]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9}$ +^([a-z0-9,!#\$%&'\*\+/=\?\^_`\{\|}~-]+(\.[a-z0-9,!#\$%&'\*\+/=\?\^_`\{\|}~-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,})){1}(;[a-z0-9,!#\$%&'\*\+/=\?\^_`\{\|}~-]+(\.[a-z0-9,!#\$%&'\*\+/=\?\^_`\{\|}~-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,}))*$ +^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$ +^\s*((([\w-]+\.)+[\w-]+|([a-zA-Z]{1}|[\w-]{2,}))@(\w+\.)+[A-Za-z]{2,5}[?= ]?[?=,;]?[?= ]?)+?$ +`.*?((http|ftp|https)://[\w#$&+,\/:;=?@.-]+)[^\w#$&+,\/:;=?@.-]*?`i +(".+"\s)??;? +((((http[s]?|ftp)[:]//)([a-zA-Z0-9.-]+([:][a-zA-Z0-9.&%$-]+)*@)?[a-zA-Z][a-zA-Z0-9.-]+|[a-zA-Z][a-zA-Z0-9]+[.][a-zA-Z][a-zA-Z0-9.-]+)[.](com|edu|gov|mil|net|org|biz|pro|info|name|museum|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ax|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)([:][0-9]+)*(/[a-zA-Z0-9.,;?'\\+&%$#=~_-]+)*) +(([\w]+:)?//)?(([\d\w]|%[a-fA-f\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}(:[\d]+)?(/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)? +((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+[\w\d:#@%/;$()~_\+-=\\\.&]*) +((http|ftp|https):\/\/w{3}[\d]*.|(http|ftp|https):\/\/|w{3}[\d]*.)([\w\d\._\-#\(\)\[\]\\,;:]+@[\w\d\._\-#\(\)\[\]\\,;:])?([a-z0-9]+.)*[a-z\-0-9]+.([a-z]{2,3})?[a-z]{2,6}(:[0-9]+)?(\/[\/a-z0-9\._\-,]+)*[a-z0-9\-_\.\s\%]+(\?[a-z0-9=%&\.\-,#]+)? +((http|ftp|https|ftps):\/\/)?[\w\-_\.]+\.(([0-9]{1,3})|([a-zA-Z]{2,3})|(aero|arpa|asia|coop|info|jobs|mobi|museum|name|travel))+(:[0-9]+)?\/?(([\w\-\.,@^%:/~\+#]*[\w\-\@^%/~\+#])((\?[a-zA-Z0-9\[\]\-\._+%\$#\=~',]*=[a-zA-Z0-9\[\]\-\._+%\$#\=~',]*)+(&[a-zA-Z0-9\[\]\-\._+%\$#\=~',]*=[a-zA-Z0-9\[\]\-\._+%\$#\=~',]*)*)?)? +((http|https|ftp|telnet|gopher|ms\-help|file|notes)://)?(([a-z][\w~%!&',;=\-\.$\(\)\*\+]*)(:.*)?@)?(([a-z0-9][\w\-]*[a-z0-9]*\.)*(((([a-z0-9][\w\-]*[a-z0-9]*)(\.[a-z0-9]+)?)|(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))(:[0-9]+)?))?(((/([\w`~!$=;\-\+\.\^\(\)\|\{\}\[\]]|(%\d\d))+)*/([\w`~!$=;\-\+\.\^\(\)\|\{\}\[\]]|(%\d\d))*)(\?[^#]+)?(#[a-z0-9]\w*)?)? +((v|[\\/])\W*[i1]\W*[a@]\W*g\W*r\W*[a@]|v\W*[i1]\W*[c]\W*[o0]\W*d\W*[i1]\W*n) +(@\s*".*?")|("([^"\\]|\\.)*?") +([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$ +([A-Z]|[a-z])|\/|\?|\-|\+|\=|\&|\%|\$|\#|\@|\!|\||\\|\}|\]|\[|\{|\;|\:|\'|\"|\,|\.|\>|\<|\*|([0-9])|\(|\)|\s +([A-Za-z0-9]+:\/\/)?([a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*)?(\/|(\/([A-Za-z0-9\:@!\$&'\(\}\*\+\-_,;=~\.]+|(%[A-F0-9]{2})+))*)(\?[A-Za-z0-9]+=[A-Za-z0-9]+(&[A-Za-z0-9]+=[A-Za-z0-9]+)*)? +([\w\-\.]*)@(([\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3})|([\w\-]+\.)+(((af|ax|al|dz|as|ad|ao|ai|aq|ag|am|aw|au|at|az|bs|bh|bd|bb|by|be|bz|bj|bm|bt|bo|ba|bw|bv|br|io|bn|bg|bf|kh|cm|ca|cv|ky|cf|td|cl|cn|cx|cc|km|cg|cd|ck|cr|ci|hr|cu|cy|cz|dk|dj|dm|do|ec|eg|sv|gq|er|ee|et|fk|fo|fj|fi|fr|gf|pf|tf|ga|gm|ge|de|gh|gi|gr|gl|gd|gp|gu|gt| gg|gn|gw|gy|ht|hm|va|hn|hk|hu|is|id|ir|iq|ie|im|il|it|jm|jp|je|jo|kz|ke|ki|kp|kr|kw|kg|la|lv|lb|ls|lr|ly|li|lt|lu|mo|mk|mg|mw|my|mv|ml|mt|mh|mq|mr|yt|mx|fm|md|mc|mn|ms|ma|mz|mm|nr|np|nl|an|nc|nz|ni|ng|nu|nf|mp|no|om|pk|pw|ps|pa|pg|py|pe|ph|pn|pl|pt|qa|re|ro|ru|rw|sh|kn|lc|pm|vc|ws|sm|st|sa|sn|cs|sc|sl|sg|sk|si|sb|so|za|gs|es|lk|sd|sr|sj|sz|se|ch|sy|tw|tj|tz|th|tl|tg|tk|to|tt|tn|tr|tm|tc|tv|ug|ua|gb|us|um|uy|uz|vu|ve|vn|vg|vi|wf|eh|ye|zm|zw|uk|com|edu|gov|int|mil|net|org|biz|info|name|pro|aero|coop|museum|arpa|co|in|ne|bi|na|pr|ae|mu|ar)))?) +([^_.]([a-zA-Z0-9_]*[.]?[a-zA-Z0-9_]+[^_]){2})@([a-z0-9]+[.]([a-z]{2,3}|[a-z]{2,3}[.][a-z]{2,3})) +([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+) +([a-zA-Z0-9\_\-\.]+[a-zA-Z0-9\_\-\.]+[a-zA-Z0-9\_\-\.]+)+@([a-zA-z0-9][a-zA-z0-9][a-zA-z0-9]*)+(\.[a-zA-z0-9][a-zA-z0-9][a-zA-z0-9]*)(\.[a-zA-z0-9]+)* +([a-zA-Z0-9_\-\.]+)(@[a-zA-Z0-9_\-\.]+) +([a-z\s.\-_'])*<\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*\> +([oO0]*)([|:;=X^])([-']*)([)(oO0\]\[DPp*>X^@]) +(\A|\s)(((>[:;=+])|[>:;=+])[,*]?[-~+o]?(\)+|\(+|\}+|\{+|\]+|\[+|\|+|\\+|/+|>+|<+|D+|[@#!OoPpXxZS$03])|>?[xX8][-~+o]?(\)+|\(+|\}+|\{+|\]+|\[+|\|+|\\+|/+|>+|<+|D+))(\Z|\s) +(\A|\s)((\)+|\(+|\}+|\{+|\]+|\[+|\|+|\\+|/+|>+|<+|D+|[@#!OoXxZS$0])[-~+o]?[,*]?((<[:;=+])|[<:;=+])|(\)+|\(+|\}+|\{+|\]+|\[+|\|+|\\+|/+|>+|<+|D+)[-~+o]?[xX8]((<(([a-zA-Z0-9"'_,.:;!?@$&()%=/ ]|[-]|[ \f]){0,})>([a-zA-Z0-9"'_,.:;!?@$&()%=/ ]|[-]|[ \f]){0,})|(([a-zA-Z0-9"'_,.:;!?@$&()%=/ ]|[-]|[ \f]){0,})){0,} + +@([_a-zA-Z]+) +@{2}((\S)+)@{2} +BV_SessionID=@@@@0106700396.1206001747@@@@&BV_EngineID=ccckadedjddehggcefecehidfhfdflg.0 +['`~!@#&$%^&*()-_=+{}|?><,.:;{}\"\\/\\[\\]] +[A-Za-z_.0-9-]+@{1}[a-z]+([.]{1}[a-z]{2,4})+ +[\d+]{10}\@[\w]+\.?[\w]+?\.?[\w]+?\.?[\w+]{2,4}/i +[\w!#$%&'*+./=?`{|}~^-]+@[\d.A-Za-z-]+ +[\w-]+@([\w-]+\.)+[\w-]+ +[\w]+\@[\w]+\.?[\w]+?\.?[\w]+?\.?[\w+]{2,4} +[^ _0-9a-zA-Z\$\%\'\-\@\{\}\~\!\#\(\)\&\^] +[^A-Za-z0-9_@\.]|@{2,}|\.{5,} +[a-zA-Z0-9_\\-]+@([a-zA-Z0-9_\\-]+\\.)+(com) +[a-z]{1}[a-z0-9\-_\.]{2,24}@tlen\.pl +[v,V,(\\/)](\W|)[i,I,1,l,L](\W|)[a,A,@,(\/\\)](\W|)[g,G](\W|)[r,R](\W|)[a,A,@,(\/\\))] +\A([0-9a-zA-Z_]{1,15})|(@([0-9a-zA-Z_]{1,15}))\Z +\d{10,12}@[a-zA-Z].[a-zA-Z].* +\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* +\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*([,;]\s*\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)* +\w+@\w+\.\w+ +^ *(([\.\-\+\w]{2,}[a-z0-9])@([\.\-\w]+[a-z0-9])\.([a-z]{2,3})) *(; *(([\.\-\+\w]{2,}[a-z0-9])@([\.\-\w]+[a-z0-9])\.([a-z]{2,3})) *)* *$ +^((([!#$%&'*+\-/=?^_`{|}~\w])|([!#$%&'*+\-/=?^_`{|}~\w][!#$%&'*+\-/=?^_`{|}~\.\w]{0,}[!#$%&'*+\-/=?^_`{|}~\w]))[@]\w+([-.]\w+)*\.\w+([-.]\w+)*)$ +^((([a-z0-9])+([\w.-]{1})?)+([^\W_]{1}))+@((([a-z0-9])+([\w-]{1})?)+([^\W_]{1}))+\.[a-z]{2,3}(\.[a-z]{2,4})?$ +^((([a-zA-Z\'\.\-]+)?)((,\s*([a-zA-Z]+))?)|([A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})))(;{1}(((([a-zA-Z\'\.\-]+){1})((,\s*([a-zA-Z]+))?))|([A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})){1}))*$ +^(((h|H)(t|T))(t|T)(p|P)((s|S)?)\:\/\/)?((www|WWW)+\.)+(([0-9]{1,3}){3}[0-9]{1,3}\.|([\w!~*'()-]+\.)*([\w^-][\w-]{0,61})?[\w]\.[a-z]{2,6})(:[0-9]{1,4})?((\/*)|(\/+[\w!~*'().;?:@&=+$,%#-]+)+\/*)$ +^(([-\w \.]+)|(""[-\w \.]+"") )?<([\w\-\.]+)@((\[([0-9]{1,3}\.){3}[0-9]{1,3}\])|(([\w\-]+\.)+)([a-zA-Z]{2,4}))>$ +^(([-\w$%&'*+\/=?^_`{|}~.]+)@(([-a-zA-Z0-9_]+\.)*)([-a-zA-Z0-9]+\.)([a-zA-Z0-9]{2,7}))?$ +^(([A-Za-z0-9\!\#\$\%\&\'\*\+\-\/\=\?\^_\`\{\|\}\~]+\.*)*[A-Za-z0-9\!\#\$\%\&\'\*\+\-\/\=\?\^_\`\{\|\}\~]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6})$ +^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$ +^(([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})+([;.](([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5}){1,25})+)*$ +^((\\\\[a-zA-Z0-9-]+\\[a-zA-Z0-9`~!@#$%^&(){}'._-]+([ ]+[a-zA-Z0-9`~!@#$%^&(){}'._-]+)*)|([a-zA-Z]:))(\\[^ \\/:*?""<>|]+([ ]+[^ \\/:*?""<>|]+)*)*\\?$ +^((\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)\s*[,]{0,1}\s*)+$ +^((http|HTTP|https|HTTPS|ftp|FTP?)\:\/\/)?((www|WWW)+\.)+(([0-9]{1,3}){3}[0-9]{1,3}\.|([\w!~*'()-]+\.)*([\w^-][\w-]{0,61})?[\w]\.[a-z]{2,6})(:[0-9]{1,4})?((\/*)|(\/+[\w!~*'().;?:@&=+$,%#-]+)+\/*)$ +^((http|https|ftp):\/\/)?((.*?):(.*?)@)?([a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])((\.[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])*)(:([0-9]{1,5}))?((\/.*?)(\?(.*?))?(\#(.*))?)?$ +^([+a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,6}|[0-9]{1,3})(\]?)$ \ No newline at end of file